如何解决Tiptap React自定义Input扩展的焦点失效问题
解决Tiptap自定义Input扩展焦点回退问题
问题根源
Tiptap编辑器默认会在点击事件触发时,强制将焦点重置到编辑器的可编辑内容区域,导致自定义输入框无法正常获取焦点。需要通过事件拦截和手动焦点控制绕过这一默认行为。
解决方案步骤
1. 修改ReactInputBlockView,添加事件拦截与焦点控制
给输入框添加ref,在点击、聚焦时阻止事件冒泡,同时手动锁定焦点到输入框:
import { NodeViewProps, NodeViewWrapper } from '@tiptap/react' import React, { useRef } from 'react' const ReactInputBlockView: React.FC<NodeViewProps> = (props) => { const inputRef = useRef<HTMLInputElement>(null) const handleInputClick = (e: React.MouseEvent) => { // 阻止事件冒泡到编辑器,避免编辑器抢焦点 e.stopPropagation() // 手动聚焦输入框 inputRef.current?.focus() } const handleInputFocus = (e: React.FocusEvent) => { // 阻止编辑器的默认焦点行为 e.stopPropagation() } return ( <NodeViewWrapper contentEditable={false} as="div" className="group relative mx-auto flex w-full h-full gap-2 flex-col pb-1 bg-white rounded border" onClick={(e) => e.stopPropagation()} // 阻止Wrapper的点击事件冒泡 > <input ref={inputRef} placeholder='Type here' onClick={handleInputClick} onFocus={handleInputFocus} className="border p-2 rounded" /> </NodeViewWrapper> ) } export default ReactInputBlockView
2. 调整InputBlock扩展的配置
保持isolating属性为true,让编辑器将该节点视为独立区域,减少焦点干扰:
import { Node } from "@tiptap/core"; import { ReactNodeViewRenderer } from "@tiptap/react"; import ReactInputBlockView from "./ReactInputBlockView"; export default Node.create({ name: "input_block", content: "text*", marks: "", group: "block", defining: true, isolating: true, // 保持开启,隔离节点与编辑器其他区域 parseHTML() { return [ { tag: "div", preserveWhitespace: "full" } ]; }, renderHTML({ HTMLAttributes }) { return ["div", HTMLAttributes]; // 传递HTMLAttributes,避免样式丢失 }, addNodeView() { return ReactNodeViewRenderer(ReactInputBlockView); } });
3. 移除不必要的全局事件监听
之前添加的selectionUpdate全局监听会干扰焦点逻辑,直接移除即可,无需在全局层面处理焦点。
原理说明
stopPropagation()阻止点击事件传递到编辑器顶层容器,避免编辑器触发默认的焦点重置逻辑isolating: true让Tiptap将该节点视为独立编辑单元,减少编辑器对节点内部元素的焦点干预- 手动调用
inputRef.current?.focus()确保输入框在点击时能正确获取焦点
内容的提问来源于stack exchange,提问作者Andrea Chello
相关产品推荐
相关产品推荐

