WYSIWYG Editor 所见即所得编辑器 what you see is what you get

富文本编辑器技术调研

底层技术:Slate 做成一个完全插件化的编辑器框架
Gitbook和 语雀都使用了Slate作为底层编辑器

大量的二次开发,会导致研发成本大增,
富文本编辑器领域,前端开发有深坑存在,上手编辑器开发需慎重,例如

  1. 用户对编辑器的使用要求越来越高,比如
    1. 合并单元格、列表多级嵌套、协同编辑、版本对比、段落标注
    2. 大家都认为这是基本需求,其实这里面的技术难度是超出大家的想象
  2. 需要拦截阻止和代理的浏览器默认行为,保证数据的完整性和正确性
  3. 内容输入的多样性,比如有:打字键入、粘贴、拖拽等,每个处理起来都相当复杂
  4. 不确定的交互意图,比如按Delete键,不同的焦点位置有不同的情况需要考虑

主流富文本编辑器的方案

用 slate.js(但不依赖 React)为内核,升级为 L1 能力
vdom 技术(基于 snabbdom.jsopen in new window )做视图更新,model 和 view 分离,增加稳定性

富文本编辑器的技术演进

image.png

  • L0 优势:技术⻔槛低,短时间内快速研发;劣势:可定制的空间⾮常有限
  • L1 优势:站在浏览器肩膀上,能够满⾜ 99% 业务场景;劣势:⽆法突破浏览器本身的排版效果
  • L2 优势:技术都掌控在⾃⼰⼿中,⽀持个性化排版;劣势:技术难度相当于⾃研浏览器、数据库

https://static001.geekbang.org/con/44/pdf/3673881710/file/%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91%E5%99%A8%E7%9A%84%E6%8A%80%E6%9C%AF%E6%BC%94%E8%BF%9B-%E7%BD%97%E9%BE%99%E6%B5%A9.pdf
富文本编辑器的技术演进 https://juejin.cn/post/7114547099739357214

富文本编辑器调研

tide JSON格式

gitee开源的编辑器
网站 https://gitee.com/oschina/tide
预览 https://oschina.gitee.io/tide

react-quill

不推荐,编辑过程卡顿明显,特别是插入图片
https://github.com/zenoamaro/react-quill 5.5k
Quill https://quilljs.com
image.png

braft-editor

https://braft.margox.cn/demos/basic
yarn add braft-editor

UI预览
image.png
全屏效果
image.png
image.png

  1. import 'braft-editor/dist/index.css'
  2. import React, { useState, useEffect, useRef } from 'react'
  3. import BraftEditor from 'braft-editor'
  4. import { debounce } from 'lodash'
  5. type IProps = {
  6. value?: string
  7. }
  8. function RichEditor({ value }: IProps, ref: React.ReactNode) {
  9. // 设置编辑器初始内容
  10. const innerHtml = BraftEditor.createEditorState(value)
  11. const [state, setState] = useState(innerHtml)
  12. useEffect(() => {
  13. if (!value) return
  14. const propsHtml = BraftEditor.createEditorState(value)
  15. setState(propsHtml)
  16. }, [value])
  17. const onChange = debounce((editorState) => {
  18. const htmlString = editorState.toHTML()
  19. setState(htmlString)
  20. }, 1000)
  21. return <BraftEditor ref={ref} value={state} onChange={onChange} />
  22. }
  23. export default forwardRef(RichEditor)

父组件获取编辑器内容

  1. import React, { useRef } from 'react';
  2. import { RichEditor } from '@components'
  3. function App() {
  4. const inputRef = useRef();
  5. function onSubmit() {
  6. // 获取编辑器实例
  7. const editorState = inputRef.current.getValue();
  8. const value = editorState.toHTML();
  9. console.log('value', value);
  10. }
  11. return (
  12. <>
  13. <RichText ref={inputRef}/>
  14. <Button onClick={onSubmit}>提交</Button>
  15. </>
  16. )
  17. }

draftjs

react 的富文本编辑器框架,不能开箱即用,但提供了很多用于开发富文本的 API。基于此,开发者能够搭建出定制化的富文本编辑器;

draftjs 有几个重要的概念:EditorState、Entity、SelectionState、CompositeDecorator
EditorState 编辑器的顶级状态对象,是一个不可变数据,表示 Draft 编辑器的整个状态,包括

  • 当前文本内容状态(ContentState)
  • 当前选择状态(SelectionState)
  • 内容的装饰器(Decorator)
  • 撤销/重做
  • 堆栈对内容所做的最新类型的更改(EditorChangeType)

draftjs缺点

显示表格结构时,编辑器将会变慢,代码也会变得复杂

simditor

https://simditor.tower.im/
图片上传方式,可以定义尺寸,具体配置还需自己去写

pell

最小最简单的 web 富文本编辑器
https://github.com/jaredreich/pell
react 案例 https://github.com/jaredreich/pell/blob/master/examples/react.md
纯 es6,无依赖
image.png

Tiptap Vue

专为 vue.js 打造
Github https://github.com/ueberdosis/tiptap
网站 https://tiptap.dev
Tiptap 最大的特点是预置的渲染,没有任何 CSS,用户可以更全面地控制段落标记和样式

  • 支持获取 HTML 字符串,开发者可以将数据储存为原始 HTML 字符串
  • 支持获取 JSON 文档的 -serializable 格式
  • 文档的可编辑性基于 contentEditable 属性