如何阻止Draft.js按下退格键时删除块并跳转光标到原子块textarea
实现方案
该需求完全可以实现,核心逻辑是拦截Draft.js的退格键事件,判断触发场景后阻止默认删除行为,再主动触发原子块内textarea的聚焦即可,具体操作步骤如下:
1. 提前拦截退格键事件
优先使用Draft.js的onKeyDown钩子在事件冒泡早期拦截退格操作,避免原子块被默认逻辑删除:
const handleKeyDown = (e) => { // 仅拦截退格键 if (e.key !== 'Backspace') return; const selection = editorState.getSelection(); // 仅处理光标在当前块最起始位置的场景:只有这个场景按退格会删除前一个块 if (selection.getAnchorOffset() !== 0) return; const currentBlockKey = selection.getAnchorKey(); const content = editorState.getCurrentContent(); const blockMap = content.getBlockMap(); const currentBlockIndex = blockMap.findKey(key => key === currentBlockKey); // 获取当前块的前一个相邻块 const prevBlock = blockMap.get(blockMap.keySeq().get(currentBlockIndex - 1)); // 前序块是原子块时拦截默认行为 if (prevBlock?.getType() === 'atomic') { e.preventDefault(); e.stopPropagation(); // 触发原子块内textarea的聚焦 focusAtomicTextarea(prevBlock.getKey()); } }
将上述方法绑定到Draft.js Editor组件的onKeyDown属性即可。
2. 给原子块的textarea绑定唯一标识
在原子块的渲染方法blockRendererFn中,给每个原子块的textarea添加和块key绑定的自定义属性,方便后续匹配DOM:
const blockRendererFn = (block) => { if (block.getType() === 'atomic') { return { component: (props) => { const blockKey = props.block.getKey(); return ( <div className="atomic-block-wrapper"> {/* 用块key作为自定义属性值做唯一标识 */} <textarea data-atomic-block-key={blockKey} placeholder="原子块输入区" /> </div> ) }, editable: false // 原子块本身设为不可编辑,避免Draft.js接管内部输入逻辑 } } }
3. 实现textarea聚焦逻辑
通过块key匹配到对应DOM后触发聚焦,还可以根据需求自定义光标在textarea中的位置:
const focusAtomicTextarea = (blockKey) => { const targetTextarea = document.querySelector(`textarea[data-atomic-block-key="${blockKey}"]`); if (targetTextarea) { targetTextarea.focus(); // 示例默认把光标放在textarea内容末尾 targetTextarea.setSelectionRange(targetTextarea.value.length, targetTextarea.value.length); } }
额外优化提示
- 如果项目不推荐直接操作DOM,可以用React Ref替代属性查询:维护一个全局的Ref Map,key为原子块的key,value为对应textarea的ref,聚焦时直接从Map中取ref调用
focus()即可,性能更好。 - 如果需要实现从原子块textarea按退格跳转回主编辑器的逻辑,同理可以拦截textarea的
onKeyDown事件,判断光标在textarea起始位置时,主动调用编辑器的focus方法,同时把编辑器选区设置到原子块的后一个块即可。
内容的提问来源于stack exchange,提问作者K. Tim
相关产品推荐
相关产品推荐

