線上富文字編輯器初探

Zuckjet發表於2022-04-28

概述

線上富文字編輯器是用於在 Web 瀏覽器中編輯文字的介面,它為使用者呈現所見即所得(WYSIWYG)的編輯區域。它的優勢是充分利用 HTML 的豐富表現能力,減少使用者對文字格式轉換的工作量。這裡的富文字是相較於純文字而言,與純文字不同的是它具有樣式、排版等資訊。

工作原理

線上富文字編輯器是如何工作的呢?語雀團隊的一位研發工程師總結的很好,即線上富文字編輯器主要解決兩個問題:

  1. 如何在瀏覽器呈現富文字。
  2. 如何在瀏覽器編輯富文字。

對於問題 1,既然線上富文字是執行在瀏覽器中,那肯定是瀏覽器支援的呈現方式。目前市面上主流的方案都是採用 HTML 標籤結合 CSS 樣式來呈現富文字,另外的一些富文字編輯器也會採用 Canvas 來呈現富文字, 比如 Google Docs。

對於問題 2,也就是如何在網頁進行文字的輸入和編輯。回憶我們平時的網頁瀏覽,絕大部分情況是在有表單元素的情況下才可進行使用者輸入, 例如我們經常用的百度搜尋,那就是一個 input 框供使用者輸入想要檢索的關鍵字。諸如 input、textarea 之類的表單元素雖然允許使用者進行文字輸入,但是它們只能輸入純文字內容,而我們要實現的卻是一個富文字編輯器。好在瀏覽器為絕大多數 HTML 元素提供了一個 contenteditable 屬性,該屬性可以用來控制元素是否可以編輯。在瀏覽器位址列輸入如下地址並訪問,那整個網頁就是一個可輸入文字的編輯器:

因為現代瀏覽器幾乎都支援該屬性,而且該屬性又可以利用瀏覽器提供的一些預設行為,因此利用該屬性實現富文字編輯器是絕大多數開發者的不二選擇。

但凡事都有例外,一些實力比較強大、以富文字編輯器為主營業務的團隊也會採用模擬游標加事件攔截來實現富文字編輯器。我們不妨思考一下,平時瀏覽網頁的時候,如何判斷一個網頁是否可以編輯的呢?概括來說就是該區域游標是可以聚焦的,且使用者通過鍵盤等裝置輸入字元的時候輸入的字元能呈現在該區域。正如一句俗語所說,如果走起來像一隻鴨子、叫起來像一隻鴨子,那麼它就是一隻鴨子。如果我們能讓網頁的一塊區域可以滑鼠聚焦,且允許使用者輸入字元在上面,那麼它就可以稱之為富文字編輯器。

以 Google Docs 為例,當你用滑鼠點選文件區域,會出現一個閃動的游標。當用瀏覽器開發者工具檢視頁面元素的時候,你會發現文件編輯區域既不是可輸入的 input 等表單元素,又沒有上文提到的 contenteditabe 屬性,那麼為什麼游標可以在該區域聚焦並且顯示字元的呢?原來你所看見的游標,只不過是用 HTML 加 CSS 實現的虛擬游標。當你用滑鼠點選文件區域的時候,頁面會攔截點選事件,並計算游標的位置,實時地繪製出一條虛擬的游標。當你輸入文字的時候,同樣是通過攔截的輸入事件獲取使用者輸入的字元,實時地顯示在文件編輯區域。使用者對這一切是無感知的,就好像真的是在一個可輸入、編輯的區域進行文字創作。

優劣對比

以 contenteditalbe 屬性實現富文字編輯功能,並用 HTML 加 CSS 展示富文字內容的這類編輯器:

優點:開箱即用,給元素加上一個屬性就可以開始編輯、輸入,另外瀏覽器提供了一些預設的行為,比如游標聚焦、選取高亮。

缺點:缺少一致性,這包括內容一致性和表現一致性。內容一致性表現為,當編輯器裡的內容看起來一樣,但實際上儲存的 HTML 結構不一致。比如當你在編輯框按下回車,是增加一個 div 標籤 還是 p 標籤,亦或是 <br/> 標籤,這在不同瀏覽器中可能發生不同的行為。表現一致性表現為,當儲存的 HTML 結構一致,在不同的瀏覽器的顯示樣式也會有不同,比如同一個 button 標籤在不同瀏覽器中外觀樣式也會不一樣。前 Medium 工程師曾經發表一篇名為 “Why ContentEditable is Terrible”的文章,對這方面感興趣的可以搜尋這篇文章閱讀了解。

自己實現模擬游標攔截使用者輸入,並用 Canvas 來展示富文字內容的這類編輯器:

優點:高一致性以及效能提升。Canvas 只是一塊畫布,本身並沒有任何內容,我們可以通過 JavaScript 在畫布上繪製影像、文字,因此它能夠做到在不同瀏覽器中表現一致。另外在編輯超大文件的時候,對文件的修改容易觸發瀏覽器的重繪、迴流,這些都會導致效能問題,而使用了 Canvas 後開發者則有了更大的優化空間。

缺點:複雜度高。滑鼠聚焦、選區等操作都要自己實現。舉例來說,你把游標移動到單詞開頭,然後拖動選取到單詞結尾,這個單詞就會高亮。在你看來這是理所當然,這是因為瀏覽器幫我們做了這些操作。如果是自己攔截使用者操作並用 Canvas 繪製,那麼這一切都要自己去實現,甚至使用者單擊滑鼠你都要判斷使用者是在單擊還是在拖選。另外通過 Canvas 繪製的富文字,是 SEO 不友好的,因為你的內容都是繪製在畫布內,搜尋引擎無法感知。同理,這對於有視覺障礙的使用者,也會帶來使用上的麻煩。

本文首發於個人公眾號,點選閱讀原文

相關文章