draftJs与基于ContentEditable的富文本编辑器的比较

1,464 阅读4分钟

对于draft与contentEditable的实验测试:

1,复制测试:

  • 当一次复制超过1W行时出现延迟卡顿
  • 6万行是卡顿效果明显
  • 12万行时 几乎接近崩溃延!延时严重浏览器无法进行其他操作

2,内容测试

  • 当行数超过6万行时
    进行编辑操作时操性能问题暴漏明显 影响操作(鼠标点击移动光标都能感觉到明显的卡顿)

性能截图:

一次性复制6万行性能对比:

draft-js :

可以看出从按下粘贴(4000ms时标)开始 一直到(16000ms时标)复制内容渲染出来结束 上方出现红条(长帧标记)导致页面卡死达12秒 这12秒的时间 约一半时间进行js运算 一半时间进行渲染。
结果:

  • 时长: 12秒

  • 渲染之后无法进行其他操作(卡顿明显)

基于contentEditable 实现

性能截图:

从复制开始到呈现内容一共时常约为3秒其中以为是浏览器提供的原生api没有呈现过多js运算的时间几乎所有的时间都在渲染上,渲染结果之后编辑器内仍然是可以正常操作的 ,虽然略微有卡顿现象但是不影响用户操作仍然可以正常使用。

结果:

  • 时长:3秒
  • 渲染之后无明显卡顿 (用户仍可正常操作)


这是在已经复制6万行的基础上进行操作 可以看出大部分的时间都发生在渲染和回流导致后续js不至于被阻塞

两种对比:
| —— | draftJs | 基于ContentEitable |
| -------- | -----: | :----: |
| 呈现时长 | 12s | 3s | | 页面卡顿情况 | 严重卡顿 | 略微卡顿 |
| 费时主要原因 | js运算+渲染 | 渲染 |
| 实现 | 基于model模型进行渲染| 浏览器原生提供|

为什么一次性复制大量的内容会有一半的时间进行js计算呢?

这就要从draftJs的渲染机制说起:
Draft.js 至上而下可以分为 Editor,EditorContents,EditorBlock,EditorLeaf 这四层,大致关系下图:

结构对应关系:

例如:当我想将“blod blodAndItatlieAndStrikeThrough”这句话部分加上删除标记时 当鼠标点击编辑器的时候,你就需要拦截事件然后查看是单点还是拖拽 ,然后计算offset,然后将重写的那几个数据结构的type重新写入到contentState指定位置就可以了。 也就是说移动光标你需要进行计算光标选中内容,光标坐落位置之类的,从而增加了js的计算量。

draft拦截和重写了所有事件,如,复制粘贴,文本改变等事件。 所以一次性复制大量的内容造成延迟时间严重,页面卡死就是因为这个原因。他需要先将所有的内容进行分析,然后分析哪些内容对应哪些type,之后生成对应的数据结构,(有点类似于虚拟dom)然后生成对应dom内容。放入到结构中。对于6万行的大量计算js运算生成对应的model结构是需要一定的时间的 然后渲染和回流也需要时间 这就是一次性复制大量内容性能大幅度落后与contentEitable的原因之一因为contentEitable调用原生api 主要时间在渲染和回流上js几乎没有消耗过多时间。

draft 缺点

1,性能和体验,根源在于它基于底层的设计和富文本的描述schema
2,无法在同一行放置两个图片 
3,性能差  内容越长性能越差 immutable能提升,但本身也是有大量运算,在大量突然的编辑下,复制粘贴各种操作,仍然明显可断。因为不是基于contenteditable的实现,因为contentditable是浏览器原生实现的不管你多长都感觉不到性能问题,文章过长可能出现闪烁问题
4,在两个block之间不好处理光标

draft 特点

1,架构新颖脱离了常用的contenteditable 方案,直接按照react模式去做,通过拦截光标鼠标等操作 更新immutable的state 最后render  通过immutable 提升渲染性能
2,可以在富文本编辑器里面渲染任意的react 组件并进行交互
3,基于React可以直接用在react 项目
4,有插件机制可以自我实现一下插件放到编辑器上

结论:

不适用于有大量文本内容需求的编辑器开发

个人观点:

如果想做出可以呈现大量内容的编辑器还要保证页面的流畅程度,更好的做法是使用底层通过contentEitable的实现,这样更加接近原生可以使页面更加流畅。如果对于内容需求不是过大的话那么draft完全可以胜任,因为他具有很好的可拓展性和灵活性,具有插件机制,可以使用网上一些比较成熟的draft-plugin进行快捷开发,还有就是他是基于react进行实现的更加符合团队人员的开发习惯,容易集成到我们现有的项目中。