Lexical 概念

介绍

  • 可扩展的 JavaScript Web 文本编辑器框架
  • 原理:一个contentEditable的元素

主要概念

Editor instances

  • 将所有内容连接在一起的核心
  • 使用createEditor()创建,使用框架绑定时,@lexical/react会自动处理

Editor States

  • 底层数据模型,包含两部分
    • a Lexical node tree
    • a Lexical selection object
  • 创建之后不可变,需通过editor.update(() => {...})更新编辑器状态
  • 获取当前编辑器状态:editor.getEditorState()
  • 编辑器状态可以完全序列化为 JSON,再使用editor.parseEditorState()序列化回编辑器

Editor Updates

  • 当您想要更改编辑器状态中的某些内容时,必须通过更新来完成editor.update(() => {...})
  • 拥有 active editor state 的完整“lexical”上下文
  • 公开了对底层编辑器状态节点树的访问

DOM Reconciler

  • Lexical 有自己的 DOM Reconciler,它采用一组 Editor States(始终是“current”和“pending”)并对它们应用“diff”。然后,使用此 diff 来仅更新 DOM 中需要更改的部分。

Listeners, Node Transforms and Commands

  • 除了调用更新之外,Lexical 完成的大部分工作都是通过 Listeners、Node Transforms 和 Commands 完成的。
const unregisterListener = editor.registerUpdateListener(({editorState}) => {
  // An update has occurred!
  console.log(editorState);
});

// Ensure we remove the listener later!
unregisterListener();
  • Commands 命令是 Lexical 中用于将所有内容连接在一起的通信系统
  • Custom commands
    1. 创建自定义 commands :createCommand() ,并分派到编辑器中:editor.dispatchCommand(command, payload)
    2. 处理 commands:editor.registerCommand(handler, priority)

如何独立于任何框架或库使用 Lexical

Creating an editor and using it

  • 编辑器实例可以被认为是负责将 EditorState 与 DOM 连接起来的实例。
  • 编辑器也是您可以注册自定义节点、添加侦听器和转换的地方
import {createEditor} from 'lexical';

// 创建编辑器实例
const config = {
  namespace: 'MyEditor',
  theme: {
    ...
  },
  onError: console.error
};
const editor = createEditor(config);

// 将编辑器实例与 a content editable <div> element 关联起来
const contentEditableElement = document.getElementById('editor');
editor.setRootElement(contentEditableElement);

// 从元素中清除编辑器实例
// editor.setRootElement(null)

Working with Editor States

  • 调用editor.getEditorState()获取编辑器状态,也可对其序列化和反序列化
const stringifiedEditorState = JSON.stringify(editor.getEditorState().toJSON());
const newEditorState = editor.parseEditorState(stringifiedEditorState);

Updating an editor

有几种方法可以更新编辑器实例(异步过程):

  • editor.update()
  • editor.setEditorState()
  • editor.registerNodeTransform()
  • editor.registerCommand(EXAMPLE_COMMAND, () => {...}, priority)
import {$getRoot, $getSelection, $createParagraphNode, $createTextNode} from 'lexical';

// Inside the `editor.update` you can use special $ prefixed helper functions.
// These functions cannot be used outside the closure, and will error if you try.
// (If you're familiar with React, you can imagine these to be a bit like using a hook
// outside of a React function component).
editor.update(() => {
  // Get the RootNode from the EditorState
  const root = $getRoot();

  // Get the selection from the EditorState
  const selection = $getSelection();

  // Create a new ParagraphNode
  const paragraphNode = $createParagraphNode();

  // Create a new TextNode
  const textNode = $createTextNode('Hello world');

  // Append the text node to the paragraph
  paragraphNode.append(textNode);

  // Finally, append the paragraph to the root
  root.append(paragraphNode);
});

如果您想知道编辑器何时更新以便对更改做出反应,可以向编辑器添加更新侦听器,如下所示:

editor.registerUpdateListener(({editorState}) => {
  // The latest EditorState can be found as `editorState`.
  // To read the contents of the EditorState, use the following API:

  editorState.read(() => {
    // Just like editor.update(), .read() expects a closure where you can use
    // the $ prefixed helper functions.
  });
});
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容