You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在contentEditable div实现用户标签系统?回车后@列表不显示问题

解决contentEditable输入框回车后@用户无法弹出列表的问题

问题根源

  1. 错误获取内容:contentEditable类型的div不存在value属性,用t.value无法拿到正确输入内容。
  2. 选区处理失效:selectionEnd是input/textarea专属属性,contentEditable元素需要用Selection和Range API来定位光标位置。
  3. 正则匹配逻辑缺陷:回车后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 22:45:39