You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Lexical编辑器中实现不可删改内容以支持填空场景?

场景背景

需要实现长文本中的填空功能,类似语言学习教材里的动词时态填空——仅填空区域可编辑,其余文本固定不可修改。
最初考虑用独立输入框对应每个填空,但跨多行输入时,要么无法查看完整文本,要么用多行文本域会导致排版混乱。之前用DraftJs实现,但在Android端测试出问题,现在转用Lexical(看中其跨平台兼容性)。

解决方案实现方案

方法一:自定义不可编辑节点(推荐)

Lexical支持创建自定义节点,你可以把固定文本封装成不可编辑的自定义节点,填空区域用默认的可编辑文本节点:

  1. 创建继承自TextNode的自定义节点,重写isEditable()方法返回false,直接阻止对该节点的编辑操作:
class FixedTextNode extends TextNode {
  static getType() {
    return 'fixed-text';
  }

  isEditable() {
    return false;
  }

  clone() {
    return new FixedTextNode(this.__text, this.__key);
  }
}
  1. 把这个自定义节点注册到编辑器配置里:
const config = {
  nodes: [FixedTextNode],
  // 其他编辑器配置
};
  1. 初始化内容时,用FixedTextNode包裹固定文本,填空区域用普通TextNode即可:
editor.update(() => {
  const root = $getRoot();
  root.append(
    $createFixedTextNode('When I arrived at the station, the train '),
    $createTextNode(''), // 这里是可编辑的填空区域
    $createFixedTextNode(' already.')
  );
});

这种方式符合Lexical的设计逻辑,不需要额外拦截状态,框架会直接保护不可编辑节点。

方法二:拦截编辑器状态变更

如果需要更细粒度的校验(比如确认固定文本未被篡改),可以通过updateListener拦截状态变更,不合法就回退到之前的状态:

  1. 注册状态更新监听器:
editor.registerUpdateListener(({editorState, prevEditorState}) => {
  const isValid = checkFixedText(editorState);
  if (!isValid) {
    editor.setEditorState(prevEditorState);
  }
});
  1. 实现校验函数,遍历节点树检查固定文本是否符合预期:
function checkFixedText(editorState) {
  let isValid = true;
  editorState.read(() => {
    const root = $getRoot();
    root.forEach(node => {
      // 假设固定文本节点类型是'fixed-text',检查内容是否正确
      if (node.getType() === 'fixed-text' && node.getTextContent() !== '预期的固定文本内容') {
        isValid = false;
      }
    });
  });
  return isValid;
}

注意:这种方式需要维护固定文本的预期值,频繁回退可能影响用户体验,优先选自定义节点方案。

额外提示

  • 可以给填空区域加下划线样式,通过给可编辑节点加CSS类或者自定义装饰节点实现,让用户更容易识别。
  • 测试时重点验证Android端的操作,确保不可编辑区域不会被误修改。

内容的提问来源于stack exchange,提问作者Andres

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:52:43