如何在contentEditable div实现用户标签系统?回车后@列表不显示问题
解决contentEditable输入框回车后@用户无法弹出列表的问题
问题根源
- 错误获取内容:contentEditable类型的div不存在
value属性,用t.value无法拿到正确输入内容。 - 选区处理失效:
selectionEnd是input/textarea专属属性,contentEditable元素需要用Selection和Range API来定位光标位置。 - 正则匹配逻辑缺陷:回车后contentEditable会生成
<br>或<p>标签,原代码的文本截取会包含上一行内容,导致无法识别当前行的@前缀单词。
修复后的代码
HTML部分
<div contenteditable="true" id="contentive" onkeyup="contentTag(event,this)"></div> <div id="result"></div>
JS部分
function contentTag(e, t) { // 获取输入框纯文本内容,排除HTML标签干扰 const inputText = t.textContent || t.innerText; // 获取当前光标选区 const selection = window.getSelection(); if (selection.rangeCount === 0) return; const range = selection.getRangeAt(0); // 计算光标在纯文本中的偏移位置 const preCursorRange = range.cloneRange(); preCursorRange.selectNodeContents(t); preCursorRange.setEnd(range.endContainer, range.endOffset); const cursorOffset = preCursorRange.toString().length; // 截取光标前的文本片段 const beforeCursor = inputText.slice(0, cursorOffset); // 匹配光标前最后一个@开头的单词(兼容换行场景) const matchResult = /(?:^|\s|\n)@(\S*)$/.exec(beforeCursor); if (matchResult) { const userName = matchResult[1]; $.ajax({ type: 'POST', url: '<?php echo $link->link('ajax', backend); ?>', data: "Name=" + userName, success: function(data) { if (data && data.trim() !== '') { $("#result").show().html(data); } else { $("#result").hide(); } } }); } else { $("#result").hide(); } }
关键修改说明
- 改用
textContent获取纯文本,避免HTML标签影响内容判断。 - 通过Range API计算光标在纯文本中的准确位置,确保截取的是光标前的有效内容。
- 优化正则表达式,仅匹配当前行(或输入开头)的@前缀单词,排除上一行内容干扰。
- 简化响应处理逻辑,统一判断空内容时隐藏列表。
内容的提问来源于stack exchange,提问作者Sadhana
相关产品推荐
相关产品推荐

