
本文介绍如何在 Quill 编辑器中使用 Mention 模块时,准确捕获用户点击下拉建议项的事件,并提取对应用户的 ID,解决原生 mention-clicked 事件仅触发于插入后而非选择时的痛点。
本文介绍如何在 quill 编辑器中使用 mention 模块时,准确捕获用户点击下拉建议项的事件,并提取对应用户的 id,解决原生 `mention-clicked` 事件仅触发于插入后而非选择时的痛点。
Quill 的 @mention 功能默认通过 mention-clicked 自定义事件通知用户已完成插入(即 mention 被写入编辑器 DOM 后),但该事件不适用于监听下拉列表中的实时点击行为——例如你希望在用户点击建议项瞬间(尚未提交到编辑器)就获取 ID 并做预处理(如加载用户资料、校验权限等)。此时需绕过事件机制,转而监听编辑器内容变更并解析 DOM 结构。
✅ 正确方案:监听 text-change + 解析 data-id
Quill 提供的 text-change 事件在每次编辑器内容变化时触发(包括 mention 插入),且 source === 'user' 可确保仅响应用户主动操作。插入后的 mention 元素会被渲染为带 data-id 属性的 <span> 标签,我们可通过正则匹配最新插入的 ID:
"jQuery点击事件遮罩弹出层可移动特效代码下载。一款jquery弹出层插件制作注册表单点击按钮弹出层表单提交效果,可支持拖到的jQuery弹出层效果。标题、高度、宽度等可以自定义弹出层js插件。
quill.on('text-change', function(delta, oldDelta, source) {
if (source !== 'user') return;
// 获取当前 HTML 内容(注意:需确保 mention 渲染已完成)
const html = quill.root.innerHTML;
// 匹配最近插入的 data-id(贪婪匹配最后一个,因新 mention 总在末尾)
const lastIdMatch = html.match(/data-id="(\d+)"[^>]*>.*?<\/span>/s);
if (lastIdMatch && lastIdMatch[1]) {
const userId = parseInt(lastIdMatch[1], 10);
console.log('用户 ID 已捕获:', userId);
// 示例:同步更新隐藏字段
document.getElementById('user_id_field').value = userId;
// ✅ 此处可执行任意业务逻辑(如 API 请求、UI 高亮等)
}
});⚠️ 注意事项与最佳实践
- 时机关键:text-change 在 mention 插入后立即触发,但 DOM 渲染可能存在微小延迟。若需更高可靠性,可结合 setTimeout(..., 0) 或 requestAnimationFrame 确保 DOM 更新完成后再解析。
- 避免重复触发:同一 mention 可能因多次输入/删除被反复插入。建议结合 delta.ops 分析具体变更操作,或用 Set 缓存已处理 ID。
-
安全解析:正则 /data-id="(\d+)"/g 仅提取数字 ID,但若数据源含特殊字符(如引号、空格),应改用 DOM API 安全解析:
const spans = quill.root.querySelectorAll('span[data-id]'); const latestSpan = spans[spans.length - 1]; if (latestSpan) { const userId = latestSpan.dataset.id; console.log('安全获取 ID:', userId); } - 兼容性提醒:Quill Mention 默认为每个 mention 添加 data-id 属性(前提是 source 返回的数据含 id 字段),请确保 suggestPeople() 返回的对象结构与文档一致。
✅ 总结
原生 mention-clicked 事件设计用于“插入完成”场景,而监听下拉列表点击需转向 text-change + DOM 解析方案。该方法稳定、无需依赖内部类名(如 #quill-mention-list,其 ID 非公开 API 且可能变动),且完全适配 Quill 的响应式更新机制。将逻辑封装为可复用函数后,即可在任何 mention 场景中快速集成用户 ID 捕获能力。

















