React中使用富文本编辑器

1,282 阅读2分钟

原文

安装和使用

使用的插件 braft-editor 地址

安装

使用npm或者yarn来将本编辑器加入到你的项目中:

# 使用npm安装
npm install braft-editor --save

# 使用yarn安装
yarn add braft-editor --save

封装组件(原文是使用class组件,本篇是使用hooks)

import BraftEditor from 'braft-editor'; // 引入编辑器组件
import 'braft-editor/dist/index.css'; // 引入编辑器样式
import { useState } from 'react';

/**
 * @setDetails 编辑函数
 * @content 输入的内容 父组件的值,渲染富文本
 */

export default ({ setDetails, content }) => {
  // 创建一个空的editorState作为初始值
  const [editorState, setEditorState] = useState(BraftEditor.createEditorState(content ?? null));

  const handleEditorChange = (e) => {
    // 更新编辑器的状态
    setEditorState(e);

    // 判断输入的内容,如果有内容,设置输入的内容;如果没有内容,设置为空字符串 ''
    if (!e.isEmpty()) {
      // 如此判断的原因,因为即使是没有内容 e.toHTML() 是一对空标签,不能直接给表单使用。
      // 可直接调用editorState.toHtml()来获取HTML格式的内容
      const value = e.toHTML();
      // 调用父组件的函数,将编辑器输入的内容传递回去
      setDetails(value);
    } else {
      // 调用父组件的函数,没有内容设置成空字符串 ''
      setDetails('');
    }
  };

  return (
    <div className="my-component">
      <BraftEditor value={editorState} onChange={handleEditorChange} />
    </div>
  );
};

在表单中使用

import ProForm from '@ant-design/pro-form';
import { Button, message, Modal } from 'antd';
import { debounce, isEqual } from 'lodash';
import { useEffect, useState } from 'react';
import Editor from './Editor';

/**
 * 组件接受参数
 * @visible  弹窗控制
 * @onCancel  弹窗关闭
 */

export default ({ visible, onCancel }) => {
  // 初始化请求接口后拿到 init 值
  const [initData, setInitData] = useState('');
  const [contentData, setContentData] = useState(undefined); // 富文本数据
  const [isDisable, setIsDisable] = useState(false); // 比较值是否发生变化
  // 定义form的实例
  const [form] = ProForm.useForm();

  // 随时根据 contentData 值监听保存按钮是否禁用
  useEffect(() => {
    console.log(contentData, initData);
    if (setIsDisable(isEqual(contentData, initData))) {
      sessionStorage.removeItem('editRDF');
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [contentData]);

  /**
   * 提交按钮
   * @needClose 是否关闭 modal
   */
  const handleOk = async (needClose = false) => {
    const values = form.getFieldsValue();

    console.log(values);

    if (needClose) {
      onCancel();
    }
    // 再次存当前的值
    // setDataSource();
    sessionStorage.removeItem('editRDF');
    return message.success('成功编辑RDF');
  };

  // 通过组件传回来的值,设置组件的值 debounce 加一个防抖
  const setDetails = debounce((content) => {
    setContentData(content);
    sessionStorage.setItem('editRDF', true);
    form.setFieldsValue({ content: content });
  }, 500);

  return (
    <Modal
      title="编辑DC RDF"
      visible={visible}
      // onOk={handleOk}
      onCancel={onCancel}
      width={1000}
      footer={[
        <Button key="back" onClick={onCancel}>
          取消
        </Button>,
        <Button key="submit" disabled={isDisable} type="primary" onClick={() => handleOk()}>
          保存
        </Button>,
        <Button
          key="submitCancel"
          disabled={isDisable}
          type="primary"
          onClick={() => handleOk(true)}
        >
          保存并关闭
        </Button>,
      ]}
    >
      <ProForm
        form={form}
        submitter={false}
        // request={async () => {
        //   // 先进行接口请求拿到该 instanceId 对应的数据
        //   const res = await infoContent({
        //     instanceId: editId,
        //   });
        //   console.log('请求返回的参数', res);
        //   // 给编辑器赋值
        //   setContentData(res.data.content);
        //   setInitData(res.data.content);
        //   return res.data;
        // }}
      >
        <ProForm.Item name="content">
          <Editor setDetails={setDetails} content={contentData} />
        </ProForm.Item>
      </ProForm>
    </Modal>
  );
};