大傢好,很高興又見面了,我是"高級前端進階",由我帶著大傢一起關註前端前沿、深入前端底層技術,大傢一起進步,也歡迎大傢關註、點贊、收藏、轉發!
什麼是 Slate
Slate 可讓開發者構建功能豐富、直觀的編輯器,例如: Medium、Dropbox Paper 或 Google Docs 中的編輯器,而代碼庫不會陷入復雜性的泥潭。
Slate 可以輕松做到這一點,因為所有邏輯都是通過一系列插件實現的,因此永遠不會受到 “核心” 中包含或不包含的內容的限制。 開發者可以將其視為構建在 React 之上的 contenteditable 的可插入實現,靈感來自於 Draft.js、Prosemirror 和 Quill 等庫。
Slate 的設計原則如下:
- 一流的插件:Slate 最重要的原則是“插件是一流的實體”,這意味著可以完全自定義編輯體驗,構建像 Medium 或 Dropbox 的復雜編輯器,而不必違背庫的假設。
- 無架構核心:Slate 的核心邏輯對將要編輯的數據的模式做了很少的假設,這意味著庫中沒有任何假設,當需要超越最基本的用例時,這些假設會讓開發者陷入困境。
- 嵌套文檔模型:Slate 使用的文檔模型是一個嵌套的遞歸樹,就像 DOM 本身一樣。 這意味著可以為高級用例創建復雜的組件,例如:表或嵌套塊引用。 但僅使用單個層次結構也很容易保持簡單。
- 與 DOM 並行: Slate 的數據模型基於 DOM,文檔是一個嵌套樹,使用選擇(Selection)和范圍(Range),並且公開所有標準事件處理程序,這意味著表或嵌套塊引用等高級行為是可能的。 幾乎任何可以在 DOM 中執行的操作,都可以在 Slate 中執行。
- 直觀的命令:Slate 文檔是使用 “命令” 進行編輯的,這些命令被設計為高級且極其直觀寫入和讀取,以便自定義功能盡可能具有表現力,從而極大地提高了推理代碼的能力。
- 協作就緒的數據模型:Slate 使用的數據模型(特別是如何將操作應用於文檔)旨在允許在頂層進行協作編輯,因此,如果決定讓編輯器進行協作,則無需重新考慮所有事情。
- 明確 “核心” 界限: 借助插件優先的架構和無模式核心,“核心” 和 “自定義” 之間的界限變得更加清晰,這意味著核心體驗不會陷入邊緣情況。
目前 Slate 在 Github 通過 MIT 協議開源,有超過 28.6k 的 star、3.2k 的 fork、158k 的項目依賴量、代碼貢獻者 560 、妥妥的前端頂級開源項目。
如何使用 Slate
安裝和 Slate 基礎使用
Slate 是一個 monorepo,分為多個 npm 包,因此要安裝隻需要執行以下操作:
yarn add slate slate-react
還需要確保安裝 Slate 的 peer 依賴項:
yarn add react react-dom
請註意,如果更願意使用 Slate 的預打包版本可以使用 yarn 添加 slate 並檢索打包的 dist/slate.js 文件! 安裝 Slate 後,需要手動導入:
// Import React dependencies.
import React, {useState} from 'react'
// Import the Slate editor factory.
import {createEditor} from 'slate'
// Import the Slate components and React plugin.
import {Slate, Editable, withReact} from 'slate-react'
使用導入之前從一個空的 App 開始:
// Define our app...
const App = () => {
return null
}
下一步是創建一個新的編輯器對象。 因為希望編輯器在渲染過程中保持穩定,因此使用不帶 setter 的 useState 鉤子:
const App = () => {
// Create a Slate editor object that won't change across renders.
const [editor] = useState(() => withReact(createEditor()))
return null
}
當然,此時還沒有渲染任何東西,所以不會看到任何變化。值得一提的是,如果使用 TypeScript 還需要使用 ReactEditor 擴展編輯器,並根據 TypeScript 文檔添加註釋。 下面的示例還包括本示例其餘部分所需的自定義類型。
// TypeScript users only add this code
import {BaseEditor, Descendant} from 'slate'
import {ReactEditor} from 'slate-react'
type CustomElement = {type: 'paragraph'; children: CustomText[] }
type CustomText = {text: string}
declare module 'slate' {
interface CustomTypes {
Editor: BaseEditor & ReactEditor
Element: CustomElement
Text: CustomText
}
}
接下來是渲染 <Slate> 上下文提供程序。
提供程序組件會跟蹤 Slate 編輯器、插件、value、selection 以及發生的任何更改, 同時必須渲染在任何 <Editable> 組件之上。 但也可以使用 useSlate hooks 向其他組件(如工具欄、菜單等)提供編輯器狀態。
const initialValue = [
{
type: 'paragraph',
children: [{text: 'A line of text in a paragraph.'}],
},
]
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
// Render the Slate context.
return <Slate editor={editor} initialValue={initialValue} />
}
可以將 <Slate> 組件視為為其下面的每個組件提供上下文。
Slate Provider 的 “value” 屬性僅用作 editor.children 的初始狀態。 如果代碼依賴於替換 editor.children 應該直接替換,而不是依賴 “value” 屬性來執行此操作。
這是與 <input> 或 <textarea> 等內容略有不同的思維模型,因為富文本文檔更加復雜,經常需要在可編輯內容旁邊包含工具欄、實時預覽或其他復雜組件。通過共享上下文,其他組件可以執行命令、查詢編輯器的狀態等。
下一步是渲染 <Editable> 組件本身, 該組件的作用類似於 contenteditable。 無論在何處渲染,其都會為最近的編輯器上下文渲染可編輯的富文本文檔。
const initialValue = [
{
type: 'paragraph',
children: [{text: 'A line of text in a paragraph.'}],
},
]
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
return (
// Add the editable component inside the context.
<Slate editor={editor} initialValue={initialValue}>
<Editable />
</Slate>
)
}
Slate 添加事件
以上示例已經安裝了 Slate 並在頁面上渲染,當用戶輸入內容可以看到更改, 但有時候想要做的不僅僅是鍵入純文本字符串。
Slate 的偉大之處在於其非常容易定制,就像習慣的其他 React 組件一樣,Slate 允許傳入在某些事件上觸發的處理程序。下面使用 onKeyDown 處理程序在按下某個鍵時更改編輯器的內容。
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
]
const App = () => {
const [editor] = useState(() => withReact(createEditor()))
return (
<Slate editor={editor} initialValue={initialValue}>
<Editable
// Define a new handler which prints the key that was pressed.
onKeyDown={event => {
console.log(event.key)
}}
/>
</Slate>
)
}
此時當在編輯器中按下某個鍵時,其相應的鍵碼將打印在控制臺中。
本文總結
本文主要和大傢介紹 Slate 富文本編輯器,其可讓開發者構建功能豐富、直觀的編輯器,例如: Medium、Dropbox Paper 或 Google Docs 中的編輯器,而代碼庫不會陷入復雜性的泥潭。因為篇幅問題,關於 Slate 主題隻是做了一個簡短的介紹,但是文末的參考資料提供了大量優秀文檔以供學習,如果有興趣可以自行閱讀。如果大傢有什麼疑問歡迎在評論區留言。
參考資料
https://github.com/ianstormtaylor/slate
https://docs.slatejs.org/walkthroughs/01-installing-slate
https://vrite.io/blog/best-js-rich-text-editors-for-2023/