Utils 模块包
Lexical 提供了一个 @lexical/utils 模块包,提供了一些通用的方法
参考
- lexical-utils - Github
- @lexical/utils - documentation
注意
其中有一些方法的名称以 $ 符号开头,它们大部分是用于修改编辑器状态 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就是影子根节点- 如果要选区/光标的 focus 焦点可延伸的一端是在文档的根节点(或影子根节点)下,则将节点
$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-inner和active这两个类名(忽略数组中非字符串的元素)- 方法
removeClassNamesFromElement(element, ...className)为给定的元素element删除 class 类名
响应性
mergeRegister(...func)用于封装一系列的注册函数
参数...func表示可以接受一系列函数作为入参(也可以是数组形式),这些函数为编辑器添加/注册侦听器,以实现响应性
返回一个函数,调用它可以一次性取消所有的注册tsconst 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,所以需要采用异步编程来使用该方法tsconst filesResult = await mediaFileReader(files, ['image/']); filesResult.forEach(file => editor.dispatchCommand('INSERT_IMAGE', { src: file.result, }));objectKlassEquals(object, objectClass)返回一个布尔值,以判断object对象实例的类型是否为 特定的objectClass类
TypeScript 类型
Lexical 支持 Typescript,在该核心模块中导出了一些类型 type,便于开发者导入到项目中进行类型检查,具体参考官方文档