
本文详解如何在 Quill 编辑器中使用 Mention 模块时,准确捕获用户点击下拉建议项(而非插入后)的原始行为,并通过 text-change 事件结合 DOM 解析提取 data-id,实现对用户 ID 的即时响应。
本文详解如何在 quill 编辑器中使用 mention 模块时,准确捕获用户点击下拉建议项(而非插入后)的原始行为,并通过 `text-change` 事件结合 dom 解析提取 `data-id`,实现对用户 id 的即时响应。
Quill Mention 插件本身并未原生提供“点击建议项”(即悬停/选中下拉列表中某条目)的专用事件,其 mention-clicked 自定义事件仅在提及项已被插入编辑器内容后触发(即用户回车或鼠标点击确认插入),而非在下拉列表中点击预览项时触发。因此,直接监听 quill-mention-list 元素的点击事件不可靠——该 DOM 节点是动态创建与销毁的,且常位于编辑器容器之外(如 document.body 下),导致 getElementById("quill-mention-list") 在初始化时几乎必然返回 null。
正确的解决思路是:利用 Quill 的 text-change 生命周期钩子,在用户完成选择并提交提及项(source === 'user')的瞬间,解析当前编辑器 HTML 中新插入的 标签所携带的 data-id 属性。Mention 模块在插入成功后,会将匹配项渲染为类似 @Fredrik Sundqvist 的结构,该属性正是我们所需的用户标识。
以下是完整、健壮的实现方案:
"jQuery点击事件遮罩弹出层可移动特效代码下载。一款jquery弹出层插件制作注册表单点击按钮弹出层表单提交效果,可支持拖到的jQuery弹出层效果。标题、高度、宽度等可以自定义弹出层js插件。
const quill = new Quill("#editor", {
placeholder: "Enter @",
modules: {
mention: {
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
mentionDenotationChars: ["@"],
source: async function(searchTerm, renderList) {
const allPeople = [
{ id: 1, value: "Fredrik Sundqvist" },
{ id: 2, value: "Patrik Sjölin" }
];
const matchedPeople = allPeople.filter(person =>
person.value.toLowerCase().includes(searchTerm.toLowerCase())
);
renderList(matchedPeople);
}
}
}
});
// ✅ 关键:监听 text-change,精准捕获插入动作
quill.on('text-change', function(delta, oldDelta, source) {
if (source === 'user') {
// 获取渲染后的 HTML(注意:root.innerHTML 更可靠,避免 innerText 丢失属性)
const html = quill.root.innerHTML;
// 使用正则提取所有 data-id(支持多次提及)
const idMatches = html.match(/data-id="(\d+)"/g);
if (idMatches && idMatches.length > 0) {
// 取最后一个匹配项(即最新插入的提及)
const lastIdMatch = idMatches[idMatches.length - 1];
const userId = lastIdMatch.match(/data-id="(\d+)"/)[1];
console.log('Selected user ID:', userId);
document.getElementById('user_id_field').value = userId;
// ✅ 可在此处触发自定义业务逻辑,如加载用户详情、发送通知等
// handleUserSelection(userId);
}
}
});
⚠️ 注意事项:
- 不要依赖 innerHTML.match() 提取全部 ID 后遍历——若编辑器中已存在历史提及,可能误读旧值;应结合 delta.ops 分析变更内容更精确,但对简单场景 lastIdMatch 已足够;
- 确保 quill.root.innerHTML 是唯一可信的数据源,quill.getText() 或 quill.getContents() 无法获取 data-id 属性;
- 若需支持多选或批量操作,建议改用 quill.getSemanticHTML()(需 Quill ≥ 1.3.7)或监听 mention-select 事件(部分社区 fork 版本支持,但官方版不提供);
- 动态 DOM(如 #quill-mention-list)不可直接绑定事件,因其生命周期由 Mention 模块内部管理,且无稳定挂载时机。
综上,放弃对下拉列表 DOM 的直接监听,转而信任 text-change + HTML 属性解析,是兼容性最佳、代码最简洁的生产级实践。










