如何使用Lexical框架移除部分链接而非整段链接?
在Lexical中仅移除选中文本的链接(保留其余链接)
Lexical的TOGGLE_LINK_COMMAND是针对整个链接节点生效的,直接调用会移除整段链接。要实现只移除选中部分的链接,核心思路是拆分原链接节点,将选中的文本剥离为普通文本,保留未选中部分的链接属性。
实现步骤与代码示例
下面是一个可直接使用的函数,专门处理这种场景:
import { $getSelection, $isRangeSelection, $getNodeByKey, $createTextNode, $createLinkNode } from 'lexical'; function removeLinkFromSelectedText(editor) { editor.update(() => { const selection = $getSelection(); // 仅处理范围类选择(不处理单光标选中) if (!$isRangeSelection(selection)) return; const { anchor, focus } = selection; const anchorNode = $getNodeByKey(anchor.key); const focusNode = $getNodeByKey(focus.key); // 校验选中内容是否属于同一个链接节点 if (anchorNode !== focusNode || !anchorNode.getParent()?.isLink()) return; const linkNode = anchorNode.getParent(); const originalUrl = linkNode.getURL(); const fullText = anchorNode.getTextContent(); // 计算选中区域的起止位置(兼容正向/反向选中) const startOffset = Math.min(anchor.offset, focus.offset); const endOffset = Math.max(anchor.offset, focus.offset); // 将文本拆分为三个部分:选中前、选中区、选中后 const beforeText = fullText.slice(0, startOffset); const selectedText = fullText.slice(startOffset, endOffset); const afterText = fullText.slice(endOffset); // 删除原链接节点 linkNode.remove(); // 重新插入带链接的前半段文本 if (beforeText) { const textNode = $createTextNode(beforeText); const newLinkNode = $createLinkNode(originalUrl); newLinkNode.append(textNode); anchorNode.getParent().insertBefore(newLinkNode); } // 插入无链接的选中文本 if (selectedText) { const textNode = $createTextNode(selectedText); anchorNode.getParent().insertBefore(textNode); } // 重新插入带链接的后半段文本 if (afterText) { const textNode = $createTextNode(afterText); const newLinkNode = $createLinkNode(originalUrl); newLinkNode.append(textNode); anchorNode.getParent().insertBefore(newLinkNode); } }); }
用法说明
- 选中你需要移除链接的文本片段(比如示例中的"repository")
- 调用这个函数:
removeLinkFromSelectedText(editor)
核心逻辑解析
Lexical中的链接是包裹文本的容器节点,单个链接节点只能对应一个URL。因此要修改部分文本的链接状态,必须将原链接节点拆分为三个部分:
- 选中前的文本:保留原链接属性
- 选中的文本:转为普通文本节点
- 选中后的文本:保留原链接属性
这样就能实现只移除选中部分的链接,其余部分的链接保持不变。
内容的提问来源于stack exchange,提问作者Pingolin
相关产品推荐
相关产品推荐

