📜  在 ReactJS 中设计一个 Markdown 笔记应用程序(1)

📅  最后修改于: 2023-12-03 15:37:30.228000             🧑  作者: Mango

在 ReactJS 中设计一个 Markdown 笔记应用程序

简介

本文将介绍如何在 ReactJS 中设计一个 Markdown 笔记应用程序。Markdown 是一种轻量级标记语言,易于学习和使用,许多人在编写文档时首选Markdown。本应用程序旨在为用户提供一个方便易用的Markdown编辑器,并能将Markdown文本转换为HTML以供预览和发布。

技术栈
  • ReactJS
  • Redux
  • React-Quill
  • Showdown
功能
  1. 编辑Markdown文本
  2. 预览Markdown渲染后的HTML效果
  3. 自动保存草稿
  4. 新增、删除笔记
  5. 修改笔记标题和内容
  6. 搜索笔记
思路

使用React-Quill作为富文本编辑器,用户编辑的文本即为Markdown格式,通过Showdown库将Markdown转换为HTML格式并渲染到预览区域。使用Redux管理应用程序状态,自动保存草稿内容。

使用LocalStorage存储笔记数据,可以在本地电脑上保存和提取笔记内容。

代码
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import ReactQuill, { Quill } from 'react-quill';
import showdown from 'showdown';
import 'react-quill/dist/quill.snow.css';

import { addNote, deleteNote, editNote, searchNotes } from '../redux/actions';
import Note from './Note';
import NoteForm from './NoteForm';
import SearchBar from './SearchBar';

const converter = new showdown.Converter();

const NotesList = ({ notes, addNote, deleteNote, editNote, searchNotes }) => {
  const [search, setSearch] = useState('');
  const [selectedNote, setSelectedNote] = useState(null);
  const [noteTitle, setNoteTitle] = useState('');
  const [noteText, setNoteText] = useState('');

  useEffect(() => {
    const savedNotes = JSON.parse(localStorage.getItem('notes'));

    if (savedNotes) {
      savedNotes.forEach(note => addNote(note.title, note.text));
    }
    // eslint-disable-next-line
  }, []);

  useEffect(() => {
    localStorage.setItem('notes', JSON.stringify(notes));
  }, [notes]);

  const handleSearch = event => {
    const value = event.target.value;
    setSearch(value);
    searchNotes(value);
  };

  const handleAddNote = event => {
    event.preventDefault();
    if (noteTitle.trim() !== '' && noteText.trim() !== '') {
      addNote(noteTitle, noteText);
      setNoteTitle('');
      setNoteText('');
    }
  };

  const handleEditNote = event => {
    event.preventDefault();
    if (noteTitle.trim() !== '' && noteText.trim() !== '' && selectedNote !== null) {
      editNote(selectedNote, noteTitle, noteText);
      setSelectedNote(null);
      setNoteTitle('');
      setNoteText('');
    }
  };

  const handleDeleteNote = id => {
    deleteNote(id);
  };

  const handleSelectNote = note => {
    setSelectedNote(note.id);
    setNoteTitle(note.title);
    setNoteText(note.text);
  };

  const handleNoteChange = value => {
    setNoteText(value);
  };

  const renderNotes = () => {
    return (
      <>
        {notes.map(note => (
          <Note
            key={note.id}
            note={note}
            handleDeleteNote={handleDeleteNote}
            handleSelectNote={handleSelectNote}
          />
        ))}
      </>
    );
  };

  const renderNoteForm = () => {
    return (
      <NoteForm
        noteTitle={noteTitle}
        noteText={noteText}
        handleNoteChange={handleNoteChange}
        handleAddNote={handleAddNote}
        handleEditNote={handleEditNote}
        selectedNote={selectedNote}
      />
    );
  };

  const renderPreview = () => {
    return notes[selectedNote] ? (
      <div
        className='preview'
        dangerouslySetInnerHTML={{ __html: converter.makeHtml(notes[selectedNote].text) }}
      ></div>
    ) : (
      <div className='preview'>
        <p>Please select a note to preview its markdown-rendered HTML here.</p>
      </div>
    );
  };

  return (
    <div className='notes'>
      <div className='notes-header'>
        <h1 className='notes-title'>Markdown Notes</h1>
        <SearchBar value={search} handleChange={handleSearch} />
      </div>
      <div className='notes-content'>
        <div className='notes-list'>{renderNotes()}</div>
        <div className='notes-preview'>{renderPreview()}</div>
        <div className='notes-form'>{renderNoteForm()}</div>
      </div>
    </div>
  );
};

const mapStateToProps = state => {
  return { notes: state.notes };
};

export default connect(mapStateToProps, { addNote, deleteNote, editNote, searchNotes })(NotesList);

结语

通过本文的介绍,你已经学会了在ReactJS中设计一个Markdown笔记应用程序。这个应用程序可以帮助你更方便地创建和编辑Markdown文本,同时也能够将文本渲染为HTML格式以供预览和发布。这是一个很好的学习ReactJS的实际项目。