TipTap/ProseMirror自定义节点CustomImage无法配置openOnClick:false问题
实现Tiptap中可添加链接的图片节点(支持编辑时不触发跳转)
核心思路
通过扩展Tiptap的Image和Link节点,实现图片可被链接包裹的结构,同时通过事件监听区分编辑状态和浏览状态的点击行为,满足需求中的交互逻辑。
步骤实现
1. 配置支持嵌套的节点
首先修改Image节点的配置,允许它被Link节点包裹;同时调整Link节点,允许包含图片类型的子节点:
import { Image } from '@tiptap/extension-image'; import { Link } from '@tiptap/extension-link'; // 扩展Image节点,允许被Link包裹 const CustomImage = Image.extend({ allowIn: ['link'], }); // 配置Link节点,允许包含image子节点,关闭默认跳转逻辑 const ConfiguredLink = Link.configure({ openOnClick: false, content: 'image block*', });
2. 实现点击行为控制
在编辑器初始化后,添加点击事件监听,判断当前状态决定是否触发跳转:
editor.on('click', ({ event, state }) => { const target = event.target; // 检测点击的是被链接包裹的图片 if (target.tagName === 'IMG' && target.parentElement.tagName === 'A') { const linkUrl = target.parentElement.href; // 判断是否处于编辑状态:编辑器聚焦、选中链接节点、或有链接编辑输入框激活 const isEditing = editor.isFocused() || state.selection.node.type.name === 'link' || document.querySelector('.link-edit-input') !== null; if (!isEditing) { // 非编辑状态触发跳转 window.open(linkUrl, '_blank'); event.preventDefault(); } // 编辑状态下不处理跳转,保留编辑交互 } });
3. 实现添加链接的交互
当选中图片时,通过工具栏按钮或右键菜单触发添加链接的逻辑:
// 示例:添加链接的工具栏按钮逻辑 const wrapImageWithLink = () => { const { state, commands } = editor; const selectedNode = state.selection.node; if (selectedNode.type.name === 'image') { const linkUrl = prompt('请输入链接地址:'); // 实际项目可替换为UI弹窗 if (linkUrl) { commands.wrapIn('link', { href: linkUrl }); } } };
关键逻辑说明
- 节点嵌套配置:通过
allowIn和content属性,确保Image可以被Link包裹,这是实现结构的基础。 - 点击状态区分:通过编辑器聚焦状态、选中节点类型、编辑元素存在性判断当前是否处于编辑状态,避免编辑时误触发跳转。
- 添加链接交互:利用Tiptap内置的
wrapIn命令,快速将选中的图片节点包裹进Link节点。
需求验证
- 未添加链接的图片可选中添加:选中图片后触发
wrapImageWithLink逻辑,即可完成链接包裹。 - 添加链接后正常跳转:非编辑状态下点击图片,会打开目标链接地址。
- 编辑链接时不触发跳转:编辑时(选中链接节点修改地址、激活链接编辑输入框),点击图片不会触发跳转,可正常编辑链接。
内容的提问来源于stack exchange,提问作者mengkheang
相关产品推荐
相关产品推荐

