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

Javascript文本着色问题:输入完成后立即着色而非按空格触发

问题:输入目标单词后无法立即着色,仅空格键触发

我用JavaScript实现文本着色时遇到问题:已配置需要着色的关键词(比如HELLO),但只有按下空格键时才会给单词上色,输入完单词的最后一个字母后不会立即变色。希望输入完目标单词(比如HELLO的最后一个字母O)时就立刻着色,不用等空格。

问题出在changeColor()函数里的键盘抬起事件(keyup)和空格判断逻辑,我尝试移除相关监听代码后功能直接失效,刚接触JS搞不定,附上代码:


解决方案

核心问题是原代码只在空格键抬起时才调用着色函数,现在改成每次按键抬起都触发着色,同时修复修改DOM后光标错位的问题。

修改要点:

  1. 移除changeColor()里的空格判断条件,让所有keyup事件都触发着色
  2. 在applyColoring函数中新增光标位置保存与恢复逻辑,避免修改HTML后光标乱跑
  3. 删掉编辑器上的onchange="changeColor()"冗余属性

修改后的完整代码

index.html

<div id="editor" contenteditable="true" oninput="showPreview();">&lt;h1&gt;This is a Heading&lt;/h1&gt;
    &lt;p&gt;This is a paragraph.&lt;/p&gt;
</div>
    
<h3>PREVIEW</h3>
<div class="preview-area">
  <iframe id="preview-window"></iframe>
</div>

style.css

#editor {
  width: 400px;
  height: 100px;
  padding: 10px;
  background-color: #444;
  color: white;
  font-size: 14px;
  font-family: monospace;
  white-space: pre;
}
.statement {
  color: orange;
}

javascript.js

function applyColoring(element) {
    var keywords = ["DIV", "DIV", "H1", "H1", "P", "P", "HELLO", "<", ">", "/"];
  
    // 保存修改前的光标位置
    const selection = window.getSelection();
    const cursorOffset = selection.rangeCount > 0 ? selection.getRangeAt(0).startOffset : 0;
    const originalText = element.innerText;
    
    var str = originalText;
    const chunks = str
      .split(new RegExp(keywords.map((w) => `(${w})`).join("|"), "i"))
      .filter(Boolean);
    const markup = chunks.reduce((acc, chunk) => {
      acc += keywords.includes(chunk.toUpperCase())
        ? `<span class="statement">${chunk}</span>`
        : `<span class='other'>${chunk}</span>`;
      return acc;
    }, "");
    element.innerHTML = markup;
    
    // 恢复光标到正确位置
    const range = document.createRange();
    const sel = window.getSelection();
    let currentNode = element.firstChild;
    let currentLength = 0;
    
    while (currentNode) {
      if (currentLength + currentNode.textContent.length >= cursorOffset) {
        range.setStart(currentNode, cursorOffset - currentLength);
        break;
      }
      currentLength += currentNode.textContent.length;
      currentNode = currentNode.nextSibling;
    }
    
    // 处理光标在末尾的情况
    if (!currentNode) {
      range.setStart(element, element.childNodes.length);
    }
    range.collapse(true);
    sel.removeAllRanges();
    sel.addRange(range);
    element.focus();
  }
  
  // CHANGE COLOR 
  function changeColor() {
    // 每次按键抬起都触发着色
    document.querySelector("#editor").addEventListener("keyup", (e) => {
      applyColoring(e.target);
    });
  }
  
changeColor()
applyColoring(document.getElementById('editor'));


//PREVIEW
function showPreview() {
    var editor = document.getElementById("editor").innerText;
    
    var frame = document.getElementById("preview-window").contentWindow.document;
    document.getElementById("preview-window").srcdoc = editor;
    frame.open();
    frame.write(editor);
    frame.close();
  }
  
showPreview()

内容的提问来源于stack exchange,提问作者Nodigap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:47:31