记BraftEditor的使用


最近的项目需要使用富文本编辑框,调研后使用BraftEditor来实现软件的文本编辑功能,在使用中,我们会遇到一些组件暂未封装或者是我们感觉其不是那么完美的一些功能,如限制富文本编辑框输入的字符个数,插入自定义表情,插入超链接文本等功能。下面就总结其使用方法。

限制输入框字符个数

使用braft-editor扩展包(max-length)

使用方式

import BraftEditor from "braft-editor";
import MaxLength from 'braft-extensions/dist/max-length';
// defaultValue的值即为字符的个数
BraftEditor.use(MaxLength({defaultValue: 100}));

缺点

其计算的字符个数是字符串的长度,实际上我们与服务侧发送的文本长度几乎都是以字节为单位进行传输,所以该方式就不适合这种情况,另外编辑框中可能存在表情,此时,使用该种方式就不会计算表情的长度。

使用BraftEditor提供的属性

BraftEditor的常用属性

<BraftEditor
        value={content}
        controls={[]}
        extendControls={[{
          type: 'component',
          key: 'btnFace',
          component: getFaceComp()
        }]}
        contentStyle={{ height: 200 }}
        // 按下回车的响应
        handleReturn={(e) => {
          console.log('handleReturn');
        }}
        // 键盘按下的响应
        handleBeforeInput={(text, editorState) => {
          console.log('handleBeforeInput');
        }}
        // 粘贴时的响应
        handlePastedText={(text, html, editorState) => {
          console.log('handlePastedText');
        }}
        // 键盘按下响应,必须使用keyBindinFn,该属性才可生效
        handleKeyCommand={(e) => {
          console.log('handleKeyCommand');
        }}
        // 键盘按下响应,绑定按键
        keyBindingFn={(e) => {
          console.log('keyBindingFn');
          return getDefaultKeyBinding(e);
        }}
        // 编辑框内容变化时的响应
        onChange={(editorState) => {
          console.log('onChange');
        }}
      />

经打日志,我们发现键盘输入文本时,这几个属性执行的先后顺序为:keyBindingFn>handleBeforeInput>onChange

使用

我们可以在keyBindingFn中计算字符长度或者文本的字节长度,超过一定数量,使用e.preventDefault()阻止向后执行。

// 字节个数
const strText = content.toText();
let byteLength = 0;
for (let index = 0; index < strText.length; index++) {
  byteLength += 128 < strText.charCodeAt(index) ? 2 : 1;
}

// 字符长度
const nLength = strText.length;
console.log('输入框中的文本长度为:', byteLength);
if (100 < byteLength) {
  e.preventDefault();
}

注意
1.使用扩展时,handleBeforeInput属性失效;
2.两种方式计算出的字符个数均为上一次文本框中的内容长度,因为只有执行onChange后,编辑框内容才发生变化。该问题还未解决。

插入自定义表情

使用ContentUtils.insertText

// 引用表情扩展
import Emoticon from 'braft-extensions/dist/emoticon';
import { ContentUtils } from 'braft-utils';
BraftEditor.use(Emoticon());

// 使用ContentUtils.insertText向编辑框插入表情
setContent(ContentUtils.insertText(content, ' ', null, {
                type: 'EMOTICON',
                mutability: 'IMMUTABLE',
                data: {
                  src: strPath
                }
              }));

注意
中间必须加’ ',具体原因未知。

使用ContentUtils.insertMedias(不推荐使用)

// 使用insertMedia插入的图片,鼠标悬浮后有brafteditor内置的东西
setContent(ContentUtils.insertMedias(
              content, [{
                type: 'IMAGE',
                url: strPath
              }]
            ));

插入超链接文本

使用ContentUtils.insertText

setContent(ContentUtils.insertText(content, 'baidu.com', ['COLOR-00F', 'UNDERLINE'], {
  type: 'LINK',
  mutability: 'MUTABLE',
  data: {
    href: 'www.baidu.com',
    target: '#'
  }

问题
设置完样式后,超链接后面的样式均为该样式,暂时不知道如何解决。

使用ContentUtils.insertHTML

setContent(ContentUtils.insertHTML(content, '<a>www.baidu.com</a>'));

以下为该篇文章运行后的截图。
在这里插入图片描述
全部代码如下,望各位大佬能够帮忙指点迷津,多多指教,互相帮助。

import BraftEditor from "braft-editor";
import { ContentUtils } from 'braft-utils';
import { EditorState, getDefaultKeyBinding } from 'draft-js';
import React from "react";
import 'braft-editor/dist/index.css';

// import MaxLength from 'braft-extensions/dist/max-length';
// 引用表情扩展
import Emoticon from 'braft-extensions/dist/emoticon';
import { Popover } from "antd";

import face1 from '../Image/1.png';
import face2 from '../Image/2.png';
import face3 from '../Image/3.png';
import face4 from '../Image/4.png';
import face5 from '../Image/5.png';
import face6 from '../Image/6.png';
import face7 from '../Image/7.png';
import face8 from '../Image/8.png';
import face9 from '../Image/9.png';
import face10 from '../Image/10.png';
import face11 from '../Image/11.png';
import face12 from '../Image/12.png';
import face13 from '../Image/13.png';

// BraftEditor.use(MaxLength({defaultValue: 10}));

BraftEditor.use(Emoticon());
const arrFace = [face1, face2, face3, face4, face5, face6, face7, face8, face9, face10, face11, face12, face13];

export default function RichEditor() {

  const [content, setContent] = React.useState(BraftEditor.createEditorState(null));
  const [bVisible, setVisible] = React.useState(false);

  function getFaceComp() {
    let arrContent = [];
    let arrRowContent = [];
    for (let nIndex = 0; nIndex < arrFace.length;) {
      const strPath = arrFace[nIndex++];
      arrRowContent.push(
        <td style={{ padding: 5 }}>
          <img onClick={() => {
             setContent(ContentUtils.insertText(content, ' ', null, {
                type: 'EMOTICON',
                mutability: 'IMMUTABLE',
                data: {
                  src: strPath
                }
              }));
            // 使用insertMedia插入的图片,鼠标悬浮后有brafteditor内置的东西
            setContent(ContentUtils.insertMedias(
              content, [{
                type: 'IMAGE',
                url: strPath
              }]
            ));
            setVisible(false);
          }} src={strPath} width={32} height={32} alt="" /></td>
      );

      if (0 === nIndex % 5) {
        arrContent.push(
          <tr>
            {arrRowContent}
          </tr>
        );

        arrRowContent = [];
        continue;
      }

      if (arrFace.length === nIndex && 0 !== arrRowContent.length) {
        arrContent.push(
          <tr>
            {arrRowContent}
          </tr>
        );
      }
    }
    return (
      <div>
        <Popover visible={bVisible} trigger={['click', 'hover']} content={arrContent}>
          <button onClick={() => {
            setVisible(!bVisible);
          }}>表情</button>
        </Popover>
      </div>);
  }

  return (
    <div style={{ width: 800, height: 500 }}>
      <BraftEditor
        value={content}
        // controls={[]}
        extendControls={[{
          type: 'component',
          key: 'btnFace',
          component: getFaceComp()
        }]}
        contentStyle={{ height: 200 }}
        handleReturn={(e) => {
          console.log('handleReturn');
        }}
        handleBeforeInput={(text, editorState) => {
          console.log('handleBeforeInput');
        }}
        handlePastedText={(text, html, editorState) => {
          console.log('handlePastedText');
        }}
        handleKeyCommand={(e) => {
          console.log('handleKeyCommand');
          // return getDefaultKeyBinding(e);
        }}
        keyBindingFn={(e) => {
          console.log('keyBindingFn');
          // 字节个数
          const strText = content.toText();
          let byteLength = 0;
          for (let index = 0; index < strText.length; index++) {
            byteLength += 128 < strText.charCodeAt(index) ? 2 : 1;
          }

          // 字符长度
          const nLength = strText.length;
          console.log('输入框中的文本长度为:', byteLength);
          if (100 < byteLength) {
            e.preventDefault();
          }
          return getDefaultKeyBinding(e);
        }}
        onChange={(editorState) => {
          console.log('onChange');
          setContent(editorState);
        }}
      />
      <div style={{ width: 500, height: 50 }}>
        <button onClick={() => {
        setContent(ContentUtils.insertText(content, 'baidu.com', ['COLOR-00F', 'UNDERLINE'], {
          type: 'LINK',
          mutability: 'MUTABLE',
          data: {
            href: 'www.baidu.com',
            target: '#'
          }
          }));

          // TODO:手动设置当前选中文本,然后设置其状态
          // let objText = JSON.parse(content.toRAW());
          // for (const key in objText.entityMap) {
          //   if ('LINK' === objText.entityMap[key].type) {
          //     const objData = objText.blocks[0].entityRanges[key];
          //     let objSelection = content.getSelection();
          //     EditorState.forceSelection(content, objSelection.merge({
          //       anchorKey: objText.blocks[0].key,
          //       anchorOffset: objData.offset,
          //       focusKey: objText.blocks[0].key,
          //       focusOffset: objData.length
          //     }));
          //   }
          // }
          // content.forceSelection(content, ({
          //   anchorKey: blockKey,
          //   anchorOffset: 0,
          //   focusKey: blockKey,
          //   focusOffset: block.getLength()
          // }));
          // RichUtils.toggleInlineStyle(content, 'UNDERLINE');
          // setContent(ContentUtils.insertHTML(content, '<a>www.baidu.com</a>'));
        }}>插入超链接</button>
        <button onClick={() => {
          setContent(ContentUtils.clear(content));
        }}>清空编辑框</button>
      </div>
    </div>
  );
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,可以使用 diffjs 来进行文本内容的比较,然后使用 BraftEditor 来展示差异数据。以下是一个简单的示例代码: ```javascript import React, { useState } from 'react'; import Diff from 'diff'; import BraftEditor from 'braft-editor'; import 'braft-editor/dist/index.css'; const originalText = '这是一段原始文本,其中有些字体是加粗和斜体的。'; const modifiedText = '这是一段修改后的文本,其中有些字体是加粗和删除线的。'; const diffText = () => { const diffResult = Diff.diffWords(originalText, modifiedText); return diffResult.map((part, index) => { const content = part.value; if (part.added) { return <span key={index} style={{ backgroundColor: 'lightgreen' }}>{content}</span>; } if (part.removed) { return <span key={index} style={{ backgroundColor: 'pink' }}>{content}</span>; } return content; }); }; const App = () => { const [editorState, setEditorState] = useState(BraftEditor.createEditorStateFromText(originalText)); const handleDiff = () => { const diffResult = Diff.diffWords(originalText, modifiedText); const diffEditorState = BraftEditor.createEditorStateFromText(diffResult.map(part => part.value).join('')); setEditorState(diffEditorState); }; return ( <div> <div> <h2>原始文本</h2> <div>{originalText}</div> </div> <div> <h2>修改后的文本</h2> <div>{modifiedText}</div> </div> <div> <h2>差异数据</h2> <div>{diffText()}</div> </div> <div> <h2>差异数据编辑器</h2> <BraftEditor value={editorState} onChange={setEditorState} /> <button onClick={handleDiff}>展示差异数据</button> </div> </div> ); }; export default App; ``` 在上面的代码中,`diffText` 函数使用 `Diff` 模块来比较原始文本和修改后的文本,并返回一个包含差异数据的数组。然后在页面中展示这个数组,使用不同的背景颜色来标注增删改的差异数据。在 `差异数据编辑器` 部分,我们使用 BraftEditor 来展示差异数据,并且提供一个按钮来触发展示差异数据的操作。当用户点击按钮时,我们再次使用 `Diff` 模块来比较原始文本和修改后的文本,并将结果转换为 BraftEditor 的编辑器状态,最终展示出差异数据。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值