Slate JS:光标在行首时如何聚焦指定区块?
问题描述
我正在使用Slate JS,编写了一段代码用于聚焦指定区块(移动光标至该区块),使用场景是:按下/键打开模态框,模态框关闭后需重新聚焦至之前所在区块。目前通过Transforms.select()实现,代码示例如下:
getCurrentBlock(editor: Editor) { const { selection } = editor; if (!selection) { return { block: null, anchor: null, focus: null }; } const { anchor, focus } = selection; const { path } = anchor const block = editor.children[path[0]] as Block; return { block, anchor, focus }; } const focusBlock = (editor, path) => { ReactEditor.focus(editor); Transforms.select(editor, { anchor: { path: [path[0], 0], offset: 0 }, focus: { path: [path[0], 0], offset: 0 }, }); }
调用方式:
const { block, anchor, focus} = getCurrentBlock(editor) const { path } = anchor focusBlock(editor, path)
这段代码多数场景正常,但光标在行首(offset=0)时失效,光标会跳至页面顶部而非目标区块。请问原因是什么?如何实现行首时也能聚焦目标区块?
原因分析与解决方案
原因
问题出在手动构造选区路径的逻辑上:当光标原本就在行首(offset=0)时,你直接将选区路径设为[path[0], 0],对应区块下的第一个文本节点。但模态框关闭后,Slate的内部选区状态与DOM焦点同步可能存在延迟,加上手动构造路径丢失了原选区的上下文信息,就会导致焦点错误跳转到页面顶部。
另外,你仅记录了锚点的路径,没有完整保存原选区的anchor和focus对象,这在处理空选区(行首offset=0的情况)时会丢失关键信息。
解决方案
方案1:复用完整的原选区信息
不需要手动构造选区,直接使用之前保存的完整anchor和focus对象,能保证选区的准确性,包括行首场景:
修改后的focusBlock函数:
const focusBlock = (editor, anchor, focus) => { ReactEditor.focus(editor); // 直接复用保存的完整选区对象 Transforms.select(editor, { anchor, focus }); }
修改调用方式:
const { block, anchor, focus} = getCurrentBlock(editor) // 传入完整的anchor和focus,而非仅路径 focusBlock(editor, anchor, focus)
方案2:使用Slate内置方法获取选区
如果只需要聚焦到区块的起始位置,而非还原精确光标位置,可以用Editor.start方法获取区块的起始选区,避免手动构造路径的错误:
const focusBlock = (editor, blockPath) => { ReactEditor.focus(editor); // 获取区块的起始位置选区 const start = Editor.start(editor, blockPath); Transforms.select(editor, start); }
调用时传入区块的路径(需确保你的Block类型包含path属性):
const { block } = getCurrentBlock(editor) if (block?.path) { focusBlock(editor, block.path); }
这个方法无论光标原本在区块的哪个位置,都能准确聚焦到区块起始位置,包括行首场景。
内容的提问来源于stack exchange,提问作者Colin Burke
相关产品推荐
相关产品推荐

