日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js input 自动换行_深入Slate.js - 拯救 ContentEditble

發布時間:2023/12/2 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js input 自动换行_深入Slate.js - 拯救 ContentEditble 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們是釘釘的文檔協同團隊,我們在做一些很有意義的事情,其中之一就是自研的文字編輯器。為了把自研文字編輯器做好,我們調研了開源社區各種優秀編輯器,Slate.js 是其中之一(實際上,自研文字編輯器前,我們就使用了很久的 Slate)。

我們團隊的同學把對 Slate 的理解,寫成了小冊子,想通過連載的形式分享給你,下面是小冊子的大綱及第 2 篇 - 「拯救 ContentEditble」。


TOC

  • 一行代碼實現富文本編輯器
  • 拯救 ContentEditable
  • Slate.js 設計
  • HTML 中的富文本
  • Slate.js 中的富文本
  • 節點尋址
  • 附錄 - 不可變數據
  • 附錄 - Memorize
  • Slate.js 是怎么工作的
  • 大腦 - Controller
  • 指令系統
  • Operation
  • 插件體系
  • Normalize
  • Decoration
  • Annotation
  • 模型與視圖的同步
  • Tiny Slate.js:實現一個 Mini Slate.js
  • 設計數據結構
  • 設計 Controller
  • 實現編輯器組件
  • Slate.js 生態現狀
  • 兼容其他格式
  • 單元測試
  • 移動端編輯器
  • 挑戰與變革
  • 難于完美的編輯器
  • 大躍進 - Slate.js 0.50
  • 附錄 - 協同理論
  • OT 算法
  • 協同調度
  • 關于作者

在富文本編輯器出現之前,瀏覽器已經具備了「展示」富文本的能力,開發者可以通過編排 HTML 和 CSS,實現對字號,字色等樣式控制。但對于用戶輸入,瀏覽器所提供的 <textarea /> 和 <input /> 都只允許用戶輸入「純文本」,能力十分單薄。

因此,如果我們能夠直接編輯 HTML 內容,也就具備了「編輯」富文本的能力。例如當我們選中文本 xxx 并按下加粗的快捷鍵后,若能生成 <b>xxx</b> 或者 <strong>xxx</strong> 這樣的 HTML,就能看到被加粗的文本。

瀏覽器為 DOM 節點提供的 contentEditble 屬性即能為節點賦予「編輯其 HTML 內容」的能力。

contentEditable:讓節點可編輯

極早期的富文本編輯器實現中,為了處理換行,就要攔截用戶的鍵盤事件,判斷用戶是按下了回車鍵后,就要為其創建一個新的段落(如生成一個 <p /> 節點),這可能是通過 document.createElement() 或者類似 API 實現的。我們可能認為在新世紀初,這樣的實現方式也持續了很長一段時間,其實早在 2000 年下半年,微軟的 Internet Explorer 5.5 便引入了 contentEditable 特性,顧名思義,讓 IE 瀏覽器中的 DOM 節點的 HTML 可以被編輯。只需要為節點聲明 contenteditable為 true,那么用戶在這個節點按下回車后,IE 就能自動為用戶生成新的段落。

時間再往前推 3 年,IE 4 引入的 designMode 已經能讓整個文檔的 HTML 內容可以被編輯,contentEditable 所做的,是讓開發者能夠更細粒度地控制節點內容的可編輯性。但比較遺憾的是,當時微軟發布的這個特性,除了一個簡要的使用文檔,沒有對可編輯性的內在行為和實現做更多描述。

行為及實現規范的缺乏,導致該特性只能在了 IE 瀏覽器中使用。剛才我們提到的,在 contentEditable 節點下,用戶敲擊回車后,瀏覽器能為之產生一個新的段落,但應該產生什么樣的段落呢?類似的問題卻沒有規范來約束。

WHATWG 成員 Anne van Kesteren 也在 2005 年發表了一篇名為 More on contenteditable 的博文,在其中列舉了同樣內容,但是結構不同的兩個 contentEditable 節點:

<!-- 例子 1 --> <div contenteditable>test</div><!-- 例子 2 --> <div contenteditable><div>test</div> </div>

當我們分別在這兩個例子中敲入回車時,在 IE 5.5 中,前者生成的新段落是一個 <p> 元素,而后者生成的卻是一個 <div>。

因此,為了推動 HTML 在瀏覽器中可編輯性的應用,WHATWG 小組開始著力于 contentEditable 的規范制定。同年 7 月,Anne van Kesteren 撰寫了第一版 contentEditable 的規范。最終,經過標準委員會的不斷努力,終于形成了 HTML 5 中的 contentEditable 規范,這也是目前幾乎所有瀏覽器所遵循的規范。

在規范中,定義了兩個角色:

  • editing host:即正被編輯的 HTML 元素。如果某個 HTML 元素開啟了 contentEditable 屬性,那么這個元素就是一個 editing host;而如果 document 開啟了 designMode,那么整個 HTML 文檔下的元素都是 editing host。
  • editable:即可編輯元素。若 HTML 元素是 editing host 的子孫,那么它就可以被編輯,另外,可編輯元素的子孫也是可編輯的(除非這些子孫被聲明了 contentEditable 為 false)。

document.execCommand :使用命令進行編輯

通過 contenteditable 及 designMode 屬性能讓 HTML 內容能夠被編輯,但是,它們所做的,僅僅是為節點或者文檔開啟 HTML 內容的編輯能力,IE 5.5 引入 contentEditable 特性時,所有的編輯行為都托管給了其自己處理,并沒有對外暴露編輯相關的 API。直到 Firefox 3 問世,其不僅支持了 contentEditable,還配套了能夠與可編輯元素進行互動的 API: document.execCommand

例如,我們想要對選中的文本加粗,就可以執行:

但是,瀏覽器提供的 document.execCommand 并非無所不能,甚至還成為了文本編輯器的實現掣肘,不僅僅是支持的「指令有限」,就連同一個指令,各瀏覽器的「實現都有可能不同」。因此,更多的編輯功能仍然需要開發者進行事件劫持等操作才能實現。

Why ContentEditable is Terrible

自從 contenteditable 被 IE 引入后,用戶在瀏覽器的撰寫文檔時,擁有了更強大的能力,各大瀏覽器廠商也紛紛跟進,但是經過十多年的發展,各個瀏覽器仍然難以戰勝特性背后的復雜性,帶來統一的實現。

幾年前,Medium Editor 的開發者之一 Nick Santos 發表過一篇著名的博文:Why ContentEditable is Terrible?,我們不妨先回顧下這篇博文,一方面了解 contentEditable 的給編輯器造成的困擾,一方面也了解編輯器為此做出了怎樣的應對。

視覺內容與實際內容的一對多關系

令用戶看見的內容為「視覺內容」,視覺內容對應的 DOM 結構為 「實際內容」,在不同的瀏覽器中,雖然用戶看到了同樣的內容,但這些內容背后卻對應了不同的 DOM 結構:

視覺內容與實際內容的一對多關系

例如下面這段文本:

The hobbit was a very well-to-do hobbit, and his name was Baggins.

在不同的瀏覽器中,有可能形成不同的 DOM 內容:

<strong><em>Baggins</em></strong> <em><strong>Baggins</strong></em> <em><strong>Bagg</strong><strong>ins</strong></em> <em><strong>Bagg</strong></em><strong><em>ins</em></strong>

視覺選區與實際選區的多對多關系

選區的情況則更加糟糕,用戶看到的選區,可能被映射為不同的 DOM 選區;而同一個 DOM 選區,用戶也會看到不同的視覺選區:

視覺選區與實際選區的多對多關系

例如,我們的 HTML 如果是:

his name was <strong><em>Baggins</em></strong>

用戶看到的光標落在 Baggins 前面,這樣的視覺選區,可以被不同的 DOM 選區表示(我們用 <cursor /> 表示光標):

his name was <cursor/><strong><em>Baggins</em></strong> his name was <strong><cursor/><em>Baggins</em></strong> his name was <strong><em><cursor/>Baggins</em></strong>

繼續在光標位置插入字符 I,由于插入位置(DOM 選區)的不同,將形成不同的內容:

  • his name was IBaggins
  • his name was IBaggins
  • his name was IBaggins

假如我們的文本是:

The hobbit was a very well-to-do hobbit, and his name was Baggins.

在 well-to- 后面換行,用戶看到的文本內容是:

The hobbit was a very well-to
do hobbit, and his name was Baggins.

換行后,DOM 選區則選中了「從第一行末尾到第二行開頭的」,那么怎么將這個選區展示給用戶呢?光標究竟應該落在第一行末尾,還是第二行開頭呢?

DOM 選區可以被映射為不同的視覺選區,也就會造成懸擺選區問題:

主流的編輯器架構

由于 contentEditable 的不可靠,Medium Editor 在架構時,通過下面兩個方式規避上面提到的問題:

  • 模型與視圖分離:編輯器自定義視圖無關的數據結構,視圖的渲染不再由瀏覽器控制,而是由編輯器控制,從而滿足「視覺與實際內容的一一映射」,避免在不同的瀏覽器中發散
  • 自定義指令:自定義編輯器的指令集,一方面能擴充編輯器能力,但更重要的一方面,是避免直接調用 document.execCommand 在不同瀏覽器形成不一致的結果

目前,主流富文本編輯器的大多也采用了這樣的架構,例如 CKEditor 5、ProseMirror、Draft.js、Slate.js 等。

接下來,我們將深入目前流行的 Slate.js ,更加細致地了解主流富文本編輯器的設計哲學和實現細節。通過閱讀后續章節,你將認識到:

  • Web 富文本編輯器的內核模型是怎么設計的,為什么要這樣設計
  • 編輯器的模型和視圖之間是如何同步的
  • 編輯器是如何通過插件體系擴展能力的
  • 編輯器是怎么支持多人協同編輯的
  • 當前 Web 富文本編輯器面臨的問題

最后,我們還會一起嘗試造一個簡化版的 Slate.js 來驗證我們的學習成果。


如果你對協同文檔技術感興趣,也可以加入下面的群(釘釘/微信),和我們一同討論。

一起討論技術

也歡迎關注本賬號,我們每周都會更新~

參考資料

  • The WHATWG Blog
  • Why ContentEditable is Terrible?
  • Wiki - WYSIWYG

總結

以上是生活随笔為你收集整理的js input 自动换行_深入Slate.js - 拯救 ContentEditble的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。