quill
API驅動設計,自定義內容和格式化,跨平臺,易用. html
CKEditor
功能強,配置靈活,ui漂亮,兼容性差vue
TinyMCE
文檔好,功能強,bug少,無外部依賴。react
UEditor
功能齊全,可是不維護了,依賴jquery,自定義起來較複雜。jquery
常見功能git
- quill.js - core.js - blots/ - block.js - break.js - container.js - cursor.js - embed.js - inline.js - scroll.js - text.js - core/ - editor.js - emitter.js - instance.js - logger.js - module.js - quill.js - selection.js - theme.js - formats/ - align.js - background.js - blockquote.js - bold.js - code.js - color.js - direction.js - font.js - formula.js - header.js - image.js - indent.js - italic.js - link.js - list.js - script.js - size.js - strike.js - table.js - underline.js - video.js - modules/ - clipboard.js 剪切板(複製粘貼) - history.js 撤銷重作 - keyboard.js 功能快捷鍵,可自定義 - syntax.js 代碼塊語法高亮,依賴highlight.js - table.js 表格 - toolbar.js 工具欄(選項可配置,工具欄html可自定義,自定義選項handlers) - uploader.js - themes/ - base.js - bubble.js - snow.js - ui/ - color-picker.js - icon.picker.js - icons.js - picker.js - tooltip.js
比較重要的是 quill.js, core.js, core/editor.js, core/quill.js, formats/, blots/
這些目錄和文件。github
Quill中的blots【block, break, container, cursor, embed, inline, scroll, text】
和formats中的【blockquote, bold, code, formula, header, image, italic, link, list, script, strike, table, underline, video】
主要利用parchment對外提供的基礎Blot來做爲可供繼承的Blot父類api
formats中的【align, background, color, direction, font, indent, size】
使用 parchment對外提供的【Attributor, ClassAttributor, StyleAttributor】
來控制樣式數組
parchment提供的Registry是用來進行blot和format的註冊。微信
delta既是表達文檔,又表達文檔修改。數據結構
delta做爲一種描述內容修改的數據結構,承擔用戶操做和DOM修改之間語言的做用
delta又做爲編輯器當前內容的 一種表達方式(數據源)
簡易流程:dom mutations -> delta
ScrollBlot是最頂層的ContainerBlot, 即root Blot, 包裹全部blots, 而且管理編輯器中的內容變化。
ScrollBlot會建立一個 MutationObserver
, 用來監控DOM更新。DOM更新時會調用ScrollBlot的update方法。在Quill的scroll blot中重寫了update方法,其中對外拋出SCROLL_UPDATE事件和mutations參數
。
if (mutations.length > 0) { this.emitter.emit(Emitter.events.SCROLL_UPDATE, source, mutations); }
而後editor會監聽SCROLL_UPDATE事件
,而後觸發editor的update方法,傳入mutations參數,而後在editor的update方法中,會依據mutations構建出對應的delta數組
,與已有的delta合併,使當前delta保持最新。
// core/quill.js // 監聽dom修改後觸發的SCROLL_UPDATE事件 this.emitter.on(Emitter.events.SCROLL_UPDATE, (source, mutations) => { const oldRange = this.selection.lastRange; const [newRange] = this.selection.getRange(); const selectionInfo = oldRange && newRange ? { oldRange, newRange } : undefined; modify.call( this, // 依據mutations來同步更新editor對應的delta () => this.editor.update(null, mutations, selectionInfo), source, ); }); // core/editor.js // 更新this.delta爲最新 update(change, mutations = [], selectionInfo = undefined) { //...some code return change; }
簡易流程:delta -> blots -> dom
例如這個API; setContents(delta: Delta, source: String = 'api'): Delta
setContents傳入delta後,會遍歷delta數組, 生成相應的Blot, Attributor, 而後生成DOM結構
,而後進行format
簡易源碼流程:
quill.setContents -> this.editor.applyDelta -> this.scroll.formatAt
vue-quill-practice
中的src/components/RichTextEditor/index.vue
提供一些示例, 可是由於是從業務代碼中拿出來的,缺乏不少依賴的東西,沒法運行。僅供參考,提供思路。
文檔:官方文檔,github, 中文文檔(有人翻譯了,可是翻譯的很差,直接看官方的吧)
插件:https://github.com/quilljs/aw...
結合vue:vue-quill-editor
結合react: react-quill