Utils 模块包

lexical
Created 7/26/2023
Updated 9/29/2023

Utils 模块包

Lexical 提供了一个 @lexical/utils 模块包,提供了一些通用的方法

参考
注意

其中有一些方法的名称以 $ 符号开头,它们大部分是用于修改编辑器状态 EditorState 的,一般只能在 editor.update(callbackFn) 的回调函数 callbackFn 中实用

编辑器状态相关

  • $restoreEditorState(editor, editorState) 基于给定的 editorState 编辑器状态,恢复编辑器的内容(包括选区,如果给定的 editorState 编辑器状态中包含选区)

节点相关

  • $insertFirst(parent, node) 将给定的节点 node 插入到父节点 parent 中,作为第一个子节点
  • $insertNodeToNearestRoot(node) 将给定的节点 node 插入到距离当前选区(光标)最近的根节点(或影子根节点)
    该方法会根据选区的类型以及位置,采用不同的插入方式 ❓
    • 如果要选区/光标的 focus 焦点可延伸的一端是在文档的根节点(或影子根节点)下,则将节点 node 会被插入到选区/光标的位置,作为根节点的直接子节点
    • 如果选区/光标的 focus 焦点可延伸的一端不在根节点(或影子根节点)下,则将节点(一般是文本节点)进行 split 拆分,再将节点 node 插入右子树的前面
    • 如果没有选区,则节点 node 会添加到编辑器的末尾,作为根节点的直接子节点,并在之后再添加一个 ParagraphNode 段落节点,并选中该段落节点(将光标移到该段落节点内)
    影子根节点

    影子根节点 ShadowRoot 是指一些节点的行为类似于根节点,一般表示局部的节点树结构的终点/树根,例如表格的单元格节点 TableCellNode 就是影子根节点

  • $splitNode(node, offset) 在特定的偏移位置 offset 对给定的节点 node(元素节点)进行「分割」,返回一个二元数组 [elementNode | null, elementNode] 它包含「分割」而得的两个节点
    提示

    方法从 lexical 的核心模块导入再直接重导出

  • $dfs(startingNode?, endingNode?) 使用深度优先 DFS 的算法遍历节点树。第一个(可选)参数 startingNode 是起始节点(默认值为 RootNode 根节点),第二个(可选)参数 endingNode 是结束节点(遇到该节点会停止搜索,会包含在最后返回的列表中)
    返回一个列表,包含所遍历到的所有节点。在数组中的每个元素都是一个对象,表示所遍历的一个节点,它具有以下属性
    • 属性 depth:该节点在节点树中的深度,例如根节点的深度是 0
    • 属性 node:是节点实例对象
    DSF 深度优先

    深度优先搜索 DFS,Deep First Search,贯彻了「不撞南墙不回头」的原则,只要没有碰壁就决不选择其它的道路,坚持向当前道路的深处挖掘(一直走到尾),常用于暴力搜索所有状态。

    深度优先搜索的核心思想是试图穷举所有的完整路径,以找到可行的路径。

  • $filter(nodes, filterFn) 使用筛选函数 filterFn 对给定的一系列节点 nodes(数组)进行过滤,最终返回一个数组,里面只包含满足条件的节点
    参数 filterFn 是一个函数,它接受一个参数,是当前所遍历节点。如果满足条件则筛选函数会返回一个节点,否则就返回 null
  • $findMatchingParent(startingNode, findFn) 从给定的节点 startingNode 开始(包含),沿着节点树向上寻找满足 findFn 筛选函数所设置的条件的祖先节点(并不包含根节点)。返回第一个满足条件的祖先节点;如果没有找到满足条件的节点,则返回 null
    参数 findFn 是一个函数,它接受一个参数,是当前所遍历的节点(开始节点 startingNode 或它的祖先节点),返回一个布尔值以表示当前节点是否满足筛选条件
  • $getNearestBlockElementAncestorOrThrow(startNode) 从给定的节点 startingNode 开始(包含),沿着节点树向上寻找祖先节点(并不包含根节点),其类型为 ElementNode 的节点,而且是 block 块级元素类型
    返回第一个类型为 ElementNode 的祖先节点,如果没有找到则抛出错误 Expected node {key} to have closest block element node.
  • $getNearestNodeOfType(node, klass) 从给定的节点 startingNode 开始(包含),沿着节点树向上寻找祖先节点,其类型为 Klass 的节点
    返回第一个满足条件的祖先节点;如果没找到就返回 null
    参数 klass 是所需匹配的节点类型的实例
  • $wrapNodeInElement(node, createElementNode) 使用 createElementNode 方法创建一个 ElementNode 元素节点作为容器,以包裹给定的 node 节点。最后返回该 ElementNode 元素节点
    参数 createElementNode 是一个函数,它会返回一个 ElementNode 元素节点作为容器

增删类名

  • addClassNamesToElement(element, ...classNames) 为给定的 HTML 元素 element 添加 class 类名
    其中 ...className 是一个数组,包含需要添加的类名。会将其中的字符串都作为 class 类名添加到元素上,而且一个字符串可以用空格来分隔多个类名
    类似 addClassNamesToElement(element, ['element-inner active', true, null]) 会为元素添加 element-inneractive 这两个类名(忽略数组中非字符串的元素)
  • 方法 removeClassNamesFromElement(element, ...className) 为给定的元素 element 删除 class 类名

响应性

  • mergeRegister(...func) 用于封装一系列的注册函数
    参数 ...func 表示可以接受一系列函数作为入参(也可以是数组形式),这些函数为编辑器添加/注册侦听器,以实现响应性
    返回一个函数,调用它可以一次性取消所有的注册
    ts
    const unRegisterAll = mergeRegister(
      editor.registerCommand(...registerCommand1 logic),
      editor.registerCommand(...registerCommand2 logic),
      editor.registerCommand(...registerCommand3 logic)
    )
    
    // call it to unRegister
    // unRegisterAll()
    
  • registerNestedElementResolver(editor, targetNode, cloneNode, handleOverlap) 注册一个节点转换器 node transform,将嵌套的 ElementNode 元素节点 targeNode 转换/整合为单一 ElementNode 的节点
    各个参数的作用
    • editor 参数:
    • targetNode 参数:是需要转换的节点类型
    • cloneNode 参数:是一个函数,它会返回一个 ElementNode 元素节点实例(类型与 targetNode 所指定的一致),作为容器来包裹内容
    • handleOverlap 参数:是一个函数,其入参是父节点和当前所需转换的节点。用于处理 targetNode 类型的节点存在重叠的场景 ❓

    返回一个函数,用于取消注册
    该方法一般用于处理 MarkNode 标记节点

其他

  • isHTMLElement(x) 返回一个布尔值,判断给定的参数 x(可以是 DOM 元素或 EventTarget 事件对象)是否为一个 HTML 元素
    提示

    方法从 lexical 的核心模块导入再直接重导出

  • isHTMLAnchorElement(x) 返回一个布尔值,判断给定的 DOM 元素 x 是否为锚元素/链接元素
    提示

    方法从 lexical 的核心模块导入再直接重导出

  • isMimeType(file, acceptableMimeTypes) 返回一个布尔值,以判断给定的 file 文件,其类型是否为所接受/支持的,参数 acceptableMimeTypes 是一个数组,里面的各个元素是字符串表示所支持的不同的 MIME 类型
  • mediaFileReader(files, acceptableMimeTypes) 读取给定的一系列多媒体文件 files(数组),参数 acceptableMimeTypes 是一个数组,用于设置所支持的不同的 MIME 类型
    支持一次性读取多个文件,返回值是一个 Promise,会按照文件在数组的顺序来依次 resolve,所以需要采用异步编程来使用该方法
    ts
    const filesResult = await mediaFileReader(files, ['image/']);
    
    filesResult.forEach(file => editor.dispatchCommand('INSERT_IMAGE', { src: file.result, }));
    
  • objectKlassEquals(object, objectClass) 返回一个布尔值,以判断 object 对象实例的类型是否为 特定的 objectClass

TypeScript 类型

Lexical 支持 Typescript,在该核心模块中导出了一些类型 type,便于开发者导入到项目中进行类型检查,具体参考官方文档


Copyright © 2025 Ben

Theme BlogiNote

Icons from Icônes