初探富文本之編輯器引擎

初探富文本之編輯器引擎

在前文中我們介紹了富文本的基礎概念,以及富文本的基本發展歷程,那麼在本文中將會介紹當前主流開源的富文本編輯器引擎。當前使用最廣泛的富文本編輯器是L1的富文本編輯器,其能滿足絕大部份使用場景,由此也誕生了非常多優秀的開源富文本引擎,這其中有僅提供引擎的編輯器例如Slate.js,也有提供了部分開箱即用的功能的例如Quill.js,也有基於這些引擎二次開發的例如Plate.js,本文主要介紹了Slate.jsQuill.jsDraft.js三款編輯器引擎。

Slate.js

slate是一個僅僅提供引擎的富文本core,簡單來說他本身並不提供各種富文本編輯功能,所有的富文本功能都需要自己來通過其提供的API來實現,甚至他的插件機制也需要通過自己來拓展,所以使用slate來構建富文本編輯器的話可定製度相當高。slate的文檔雖然不是特別詳細,但是他的示例是非常豐富的,在文檔中也提供了一個演練作爲上手的基礎,對於新手還是比較友好的。話說回來如果只提供一個引擎的話,誰也不知道應該怎麼用哈哈。

slate的文檔中有對於框架的設計原則上的描述:

  • 插件是一等公民,slate最重要的部分就是插件是一等公民實體,這意味着你可以完全定製編輯體驗,去建立像Medium或是Dropbox這樣複雜的編輯器,而不必對庫的預設作鬥爭。
  • 精簡的schema核心,slate的核心邏輯對你編輯的數據結構進行的預設非常少,這意味着當你構建複雜用例時,不會被任何的預製內容所阻礙。
  • 嵌套文檔模型,slate文檔所使用的模型是一個嵌套的,遞歸的樹,就像DOM一樣,這意味着對於高級用例來說,構建像表格或是嵌套引用這樣複雜的組件是可能的,當然你也可以使用單一層次的結構來保持簡單性。
  • DOM相同,slate的數據模型基於DOM,文檔是一個嵌套的樹,其使用文本選區selections和範圍ranges,並且公開所有的標準事件處理函數,這意味着像是表格或者是嵌套引用這樣的高級特性是可能的,幾乎所有你在DOM中可以做到的事情,都可以在slate中做到。
  • 直觀的指令,slate文檔執行命令commands來進行編輯,它被設計爲高級並且非常直觀地進行編輯和閱讀,以便定製功能儘可能地具有表現力,這大大的提高了你理解代碼的能力。
  • 可協作的數據模型,slate使用的數據模型特別是操作如何應用到文檔上,被設計爲允許協同編輯在最頂層,所以如果你決定要實現協同編輯,不必去考慮徹底重構。
  • 明確的核心劃分,使用插件優先的結構和精簡核心,使得核心和定製的邊界非常清晰,這意味着核心的編輯體驗不會被各種邊緣情況所困擾。

示例

這樣一段文本數據結構如下所示。

[
  {
    children: [
      { text: "這樣" },
      { text: "一段文本", italic: true },
      { text: "的" },
      { text: "數據結構", bold: true },
      { text: "如下所示。" },
    ],
  },
];

優勢

  • 可定製化程度非常高,幾乎所有富文本表現層的功能都需要自行實現。
  • 非常輕量,本體只有一個內核,需要什麼就做什麼功能,體積可控。
  • 在設計架構時就針對協同提供了OP化的差量變更操作。
  • 數據結構是類似於DOM的嵌套JSON結構,比較直觀容易理解。

不足

  • 依舊處於Beta階段,可能會有重大API變化,例如0.50版本就是全新重構的。
  • 雖然有協同的設計,但沒有轉換操作的OT算法或CRDT算法的直接支持。
  • 僅有內核的架構同樣也是不足,所有的功能都需要自行實現,成本比較高。
  • 新版slate是無schema的,這也就意味着Normalize需要自行實現。

參考

  • slate官方文檔https://docs.slatejs.org/
  • slate官方示例https://www.slatejs.org/examples/richtext
  • 個人基於slate實現的富文本編輯器https://github.com/WindrunnerMax/DocEditor
  • 基於slate的開箱即用富文本編輯器https://plate.udecode.io/docs/playground
  • slateOT協同實現參考https://github.com/solidoc/slate-ot
  • slate協同的OTTypes參考https://github.com/pubuzhixing8/ottype-slate
  • slateCRDT協同實現參考https://github.com/humandx/slate-automerge
  • slateYJS協同結合的參考https://github.com/BitPhinix/slate-yjs
  • 關於slate非常不錯的文章https://github.com/yoyoyohamapi/book-slate-editor-design

Quill.js

quill是一個現代富文本編輯器,具備良好的兼容性及強大的可擴展性,還提供了部分開箱即用的功能。quill是在2012年開源的,quill的出現給富文本編輯器帶了很多新的東西,也是目前開源編輯器裏面受衆非常大的一款編輯器,至今爲止的生態已經非常的豐富,可以在Github等找到大量的示例,包括比較完善的協同實例。

quill的文檔中有對於框架的設計原則上的描述:

  • API驅動設計,quill所有的功能都是通過API來實現的並且可以直觀的通過API來獲得數據的變化,以文本爲中心的基礎上構建的API,不需要解析HTML或者DIFF DOM樹,這樣的設計可以讓quill的功能更加的靈活與更高的可拓展性。
  • 自定義內容和格式,quill公開了自己的文檔模型,這是對DOM的強大抽象,允許擴展和定製,由此數據結構的主角變成了BlotsParchmentDelta
  • 跨平臺,quill有着比較良好的兼容性,在舊版本的瀏覽器中也可以相同的方式運行,在用戶體驗上不同瀏覽器中也可以有着相同的視圖與交互效果,並且可以在桌面和移動設備上使用。
  • 易於使用,quill攜帶了部分開箱即用的功能,如果不需要定製的話,這些功能已經足夠了,同時quill又有着非常高的可拓展性,用來自定義各種功能。

示例

這樣一段文本數據結構如下所示。

{
  ops: [
    { insert: "這樣" },
    { insert: "一段文本", attributes: { italic: true } },
    { insert: "的" },
    { insert: "數據結構", attributes: { bold: true } },
    { insert: "如下所示。\\n" },
  ],
};

優勢

  • API驅動設計,基礎功能的支持很豐富,並且支持拓展。
  • 實現了視圖層,實現上與框架無關,無論是Vue還是React都可以輕鬆使用。
  • 使用了更加直觀的Delta來描述數據結構,本身實現了操作轉換的邏輯,可以非常方便地實現協同。
  • 生態非常豐富,有着非常多的插件與設計方案可以參考,特別是對於協同的支持可參考的地方非常多。

不足

  • Delta數據結構是扁平的,也就是一維的數據結構,這樣在實現例如表格的功能時就比較麻煩。
  • quill 2.0已經開發了很久了,但是還沒有正式發佈,目前的1.3.7版本已經有很多年沒有更新了。
  • quill自帶的功能很豐富,但這也就意味着其包的大小會比較大一些。

參考

  • quill官方文檔https://quilljs.com/docs/quickstart/
  • quill官方示例https://quilljs.com/standalone/full/
  • quillDelta設計與實現https://quilljs.com/docs/delta/
  • quill協同的OTTypes參考https://github.com/ottypes/rich-text
  • quillOT協同實現參考https://github.com/share/sharedb/tree/master/examples/rich-text
  • quillCRDT-yjs的協同實現參考https://github.com/yjs/y-quill

Draft.js

draft是用於在React中構建富文本編輯器的框架,其爲創建和自定義文本編輯器提供了強大的API,並且旨在易於擴展和與其他庫集成,與React結合可以使開發者在進行編輯器開發時既不用操作DOM、也不用單獨學習一套構建UI的範式,而是可以直接編寫React組件實現編輯器的UIdraft整體理念與React非常的吻合,例如使用狀態管理保存數據結構、使用immutable.js庫、數據結構的修改基本全部代理了瀏覽器的默認行爲、通過狀態管理的方式修改富文本數據等。

draftREADME中有對於框架的設計原則上的描述:

  • 可擴展和可定製,提供了構建塊來創建各種豐富的文本組合體驗,從基本文本樣式到嵌入式媒體的支持。
  • 聲明式富文本,draft無縫融入React,使用React用戶熟悉的聲明式的API抽象出渲染、選擇和輸入行爲的細節。
  • 不可變的編輯器狀態,draft模型是使用immutable.js構建的,提供具有功能狀態更新的API,並積極利用數據持久性來實現可擴展的內存使用。

示例

這樣一段文本數據結構如下所示。

{
  blocks: [
    {
      key: "3eesq",
      text: "這樣一段文本的數據結構如下所示。",
      type: "unstyled",
      depth: 0,
      inlineStyleRanges: [
        { offset: 2, length: 4, style: "ITALIC" },
        { offset: 7, length: 4, style: "BOLD" },
      ],
      entityRanges: [],
      data: {},
    },
  ],
  entityMap: {},
};

優勢

  • 具有靈活的API,可以輕鬆地擴展和自定義塊和內聯元素等。
  • 使用React作爲UI層以及數據管理,可以充分利用React生態,對React用戶友好。
  • 沒有過重大的Breaking Change,在穩定性與細節的處理上比較具有優勢。

不足

  • 完全依賴於React作爲UI層,與React深度綁定,在其他UI框架上很難使用。
  • 數據結構模型的設計上不是很靈活,在實現表格等嵌套結構時比較受限。
  • draft針對性能進行了大量優化,但是在呈現大量內容時還是會感受到卡頓。

參考

  • draft官方文檔https://draftjs.org/docs/overview
  • draft官方示例https://draftjs.org/
  • draftcodesandbox示例https://codesandbox.io/s/github/gupta-piyush19/Draft-JS-Editor

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://github.com/hzjswlgbsj/blog
https://zhuanlan.zhihu.com/p/425265438
https://jkrsp.com/slate-js-vs-draft-js/
https://www.zhihu.com/question/404836496
https://www.zhihu.com/question/449541344
https://juejin.cn/post/6844903838982340622
https://juejin.cn/post/7034480408888770567
https://juejin.cn/post/6974609015602937870
https://github.com/cudr/slate-collaborative
https://blog.logrocket.com/what-is-slate-js-replace-quill-draft-js/
https://dev.to/charrondev/getting-to-know-quilljs---part-1-parchment-blots-and-lifecycle--3e76
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章