打造Flutter高性能富文本編輯器——協(xié)議篇
2022-11-17|10:07|發(fā)布在分類 / 淘寶軟件| 閱讀:123
2022-11-17|10:07|發(fā)布在分類 / 淘寶軟件| 閱讀:123
閑魚作為一個二手閑置交易平臺,賣家發(fā)布商品產(chǎn)出優(yōu)質(zhì)的供給尤為重要;商品發(fā)布器希望擁有富文本編輯能力,讓用戶簡單便捷的方式產(chǎn)出更加優(yōu)質(zhì)的內(nèi)容;Flutter本身沒有富文本編輯器的能力的,只有最基礎(chǔ)的文本編輯器TextField;對于更加復(fù)雜的場景,比如支持自定義表情、主題、有序段落等能力,目前flutter組件是無法滿足我們的業(yè)務(wù)訴求,另外在交互體驗上與Native仍然存在一定的差距;為了解決業(yè)務(wù)中面臨的以上問題,我們決定設(shè)計并實現(xiàn)一個Flutter場景下高性能、可擴(kuò)展的富文本編輯器。
富文本編輯器整體架構(gòu)設(shè)計
首先我們來看一看整體的架構(gòu)設(shè)計分層:
自下而上主要分四層:
富文本編輯器對大家來說并不陌生,發(fā)展至今,已經(jīng)涌現(xiàn)出非常多有優(yōu)秀的開源富文本編輯器;當(dāng)我們想要做Flutter富文本協(xié)議的時候,第一個想法就是先了解優(yōu)秀的開源富文本編輯器方案,避免閉門造車;
目前比較優(yōu)秀的開源富文本編輯器,如CKEditor、Quill、Prosemirror、Draft、Slate等等;在了解和對比過后,我們決定使用Slate作為我們的富文本編輯器的協(xié)議;
我們?yōu)槭裁催x擇Slate?
插件是一等公民,能夠很好的滿足我們對于擴(kuò)展性的要求;
Slatjs在設(shè)計上支持嵌套結(jié)構(gòu),可以滿足復(fù)雜的業(yè)務(wù)場景;
與Dom相同的Data model,對于后面flutter渲染層的實現(xiàn),也變得更加方便;
直觀的指令設(shè)計,能夠非常好的支持plugin的自定義擴(kuò)展;
Slate在設(shè)計上,協(xié)議層與渲染層是有明確的核心劃分,這讓我們可以復(fù)用Slate協(xié)議層的設(shè)計,渲染層交給flutter來處理;
除了上面的原因,我們選擇Slate另外一個很重要的原因,就是它的單元測試覆蓋率和完整度,讓我們對它的穩(wěn)定性更有信心;
協(xié)議層的整體架構(gòu)設(shè)計如下圖:
下面我們就以Slate為例,來看一看富文本編輯器的協(xié)議層設(shè)計,需要定義的核心概念和模塊:
Slate定義了三種類型的Node節(jié)點:
Editor抽象接口定義如下:
Element
Element節(jié)點比較特殊,既是Ancentor節(jié)點,作為容器節(jié)點包含子節(jié)點;同時又是Descendant節(jié)點,可以作為其他容器節(jié)點的子節(jié)點存在。
Text節(jié)點是樹中的最低級葉子節(jié)點,描述了文本內(nèi)容以及其他自定義的渲染元素;所有的自定義屬性都包含在properties屬性中:
我們以下面這這段富文本為例:
最終這樣一段富文本對應(yīng)的Mode定義如下:
可以看到,Model的樹形結(jié)構(gòu)還是比較簡單的,所有的屬性都存放在properties字段中,這也非常方便實現(xiàn)自定義擴(kuò)展;Flutter渲染層根據(jù)Node節(jié)點的Type以及properties屬性,將富文本內(nèi)容渲染到屏幕上;
接下來需要富文本Commond協(xié)議的設(shè)計,用戶的每一次的文字輸入、刪除、文字加粗、換行等操作都是一次Command指令;Slate抽象定義了九個最基本的Operations,協(xié)議層所有的Commond指令,最終在協(xié)議層,都會轉(zhuǎn)換成一個或者多個operation操作:
下面我們通過對選中文本加粗操作為例,來了解Slate協(xié)議層Commond的處理過程:
對選中文本加粗這樣一個Commond,協(xié)議層會將這個Commond拆解成三個Opeartion:
當(dāng)一個Commond被協(xié)議層拆分成一個或者多個Opeartion執(zhí)行之后,會執(zhí)行一個非常重要的操作——Normalizing;
每一次Command操作,絕大部分情況會對Model進(jìn)行相應(yīng)修改;我們需要一個秩序維護(hù)者——Normalizing,時刻保證對協(xié)議Model修改過之后,保持?jǐn)?shù)據(jù)結(jié)構(gòu)的正確性;
Slate定義了幾個基本的內(nèi)置Normalizing規(guī)則:
每一次Commond之后,Editor都會調(diào)用normalizeNode方法,在Normalizing的過程中,發(fā)現(xiàn)存在協(xié)議結(jié)構(gòu)錯誤,需要進(jìn)行錯誤修復(fù);
Normalizing的另一個強(qiáng)大之處在于,我們可以通過自定義Normalizing,添加自定義的校驗規(guī)則,實現(xiàn)自定義的需求;在后面的業(yè)務(wù)擴(kuò)展章節(jié)會,我們會具體講解如何通過自定義Normalizing快速實現(xiàn)一個自定義主題的能力;
總結(jié)
目前Mural已經(jīng)在閑魚商品發(fā)布、商品詳情、消息等場景落地,支持了自定義表情、主題等業(yè)務(wù)能力,用戶體驗方面也有了非常大的提升。
本次主要介紹了富文本編輯器Mural整體的架構(gòu)設(shè)計以及協(xié)議層的設(shè)計;后續(xù)我們會系列文章的方式介紹Mural在渲染層的設(shè)計、自定義擴(kuò)展設(shè)計,以及交互體驗、性能方面的優(yōu)化實踐,敬請期待!
參考鏈接:
[1] Slate:https://github.com/ianstormtaylor/slate
這個問題還有疑問的話,可以加幕.思.城火星老師免費咨詢,微.信號是為: msc496。
推薦閱讀:
著作權(quán)-阿里巴巴旗下網(wǎng)站和其他網(wǎng)站和天貓代銷申訴要求
更多資訊請關(guān)注幕 思 城。
微信掃碼回復(fù)「666」
別默默看了 登錄\ 注冊 一起參與討論!