快速入門 (Vanilla JS)
本節介紹如何在不依賴任何框架或庫的情況下使用 Lexical。如果您打算在 React 應用中使用 Lexical,建議您查看 React 的入門頁面。
創建和使用編輯器
在使用 Lexical 時,通常會使用一個編輯器實例。編輯器實例可被視為將 EditorState
與 DOM 連接起來的中介。編輯器也是註冊自定義節點、添加監聽器和進行轉換的地方。
編輯 器實例可以從 lexical
包中創建,並接受一個可選的配置對象,用於主題設置和其他選項:
import {createEditor} from 'lexical';
const config = {
namespace: 'MyEditor',
theme: {
...
},
onError: console.error
};
const editor = createEditor(config);
當您擁有一個編輯器實例後,在準備就緒時,可以將該編輯器實例與文檔中的可編輯 <div>
元素關聯起來:
const contentEditableElement = document.getElementById('editor');
editor.setRootElement(contentEditableElement);
如果要從元素中清除編輯器實例,可以傳遞 null
。或者,如果需要,可以切換到另一個元素,只需將另一個元素引用傳遞給 setRootElement()
。
操作編輯器狀態
在 Lexical 中,數據源不在 DOM 中,而是在與編輯器實例相關聯的底層狀態模型中。您可以通過調用 editor.getEditorState()
獲取最新的編輯器狀態。
編輯器狀態可以序列化為 JSON,編輯器實例提供了一個有用的方法來反序列化字符串化 的編輯器狀態。
const stringifiedEditorState = JSON.stringify(editor.getEditorState().toJSON());
const newEditorState = editor.parseEditorState(stringifiedEditorState);
更新編輯器狀態
儘管使用 @lexical/rich-text
或 @lexical/plain-text
幫助包時不一定需要此操作,但對於程式化內容修改以及自定義編輯器的微調仍然是相關的。
有幾種方法可以更新編輯器實例:
- 使用
editor.update()
觸發更新 - 通過
editor.setEditorState()
設置編輯器狀態 - 通過
editor.registerNodeTransform()
在現有更新中應用變更 - 使用
editor.registerCommand(EXAMPLE_COMMAND, () => {...}, priority)
的命令監聽器
更新編輯器的最常見方法是使用 editor.update()
。調用此函數需要傳遞一個函數,以便訪問和修改底層的編 輯器狀態。當開始新的更新時,當前的編輯器狀態會被克隆並作為起點。從技術上講,這意味著 Lexical 在更新期間使用了一種稱為雙緩衝的技術。這裡有一個表示當前在屏幕上顯示的編輯器狀態,還有一個表示未來變更的進行中編輯器狀態。
創建更新通常是異步過程,這允許 Lexical 在單個更新中將多個更新一起批量處理,從而提高性能。當 Lexical 準備將更新提交給 DOM 時,更新中的底層變更和變動將形成一個新的不可變的編輯器狀態。調用 editor.getEditorState()
會返回基於更新變更的最新編輯器狀態。
以下是如何更新編輯器實例的示例:
import {
$getRoot,
$getSelection,
$createParagraphNode,
$createTextNode,
} from 'lexical';
// 在 `editor.update` 中,您可以使用特殊的 $ 前綴的幫助函數。
// 這些函數不能在閉包外部使用,否則會報錯。
// (如果您熟悉 React,可以將其想像成有點像在 React 函數組件外部使用鉤子)。
editor.update(() => {
// 從 EditorState 中獲取 RootNode
const root = $getRoot();
// 從 EditorState 中獲取選擇
const selection = $getSelection();
// 創建一個新的 ParagraphNode
const paragraphNode = $createParagraphNode();
// 創建一個新的 TextNode
const textNode = $createTextNode('Hello world');
// 將文本節點附加到段落中
paragraphNode.append(textNode);
// 最後,將段落附加到根節點
root.append(paragraphNode);
});
需要注意的是,核心庫 (lexical
包) 不會自動監聽任何命令或根據用戶事件對編輯器狀態進行更新。 要在編輯器中看到文本和其他內容,您需要註冊命令監聽器並在回調中更新編輯器。Lexical 提供了一些幫助包,使得將很多您可能想要的基本命令輕鬆地用於純文本或富文本體驗。
如果您想在編輯器更新時獲取通知以便做出響應,可以向編輯器添加更新監聽器,如下所示:
editor.registerUpdateListener(({editorState}) => {
// 最新的 EditorState 可以作為 `editorState` 找到。
// 要讀取 EditorState 的內容,使用以下 API:
editorState.read(() => {
// 就像 editor.update() 一樣,.read() 需要一個閉包,您可以在其中使用 $ 前綴的幫助函數。
});
});
綜合運用
這裡我們有最簡單的 Lexical 設置,包含富文本配置 (@lexical/rich-text
),啟用了歷史 (@lexical/history
) 和無障礙 (@lexical/dragon
) 功能。