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

JS文本着色脚本无法自动触发,仅空格键生效问题求助

解决JavaScript文本着色仅空格键触发及页面加载自动着色问题

你的问题出在三个核心点:

  1. 着色逻辑被绑定在仅空格键触发的keyup事件判断里,其他按键自然不会触发着色
  2. 页面加载时没有主动执行着色代码,只有触发指定按键才会运行逻辑
  3. contenteditable元素的onchange事件触发条件极为苛刻,基本无法用于实时内容变化监听

下面是修改后的完整代码,同时解决了所有问题:


修改后的index.html

<div id="editor" contenteditable="true">&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>

说明:移除了内联的oninput/onchange属性,改用JS统一绑定事件,代码结构更清晰


修改后的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;
}
.other {
  color: white; /* 明确设置默认文本颜色,避免修改HTML后出现继承问题 */
}

修改后的javascript.js

const editor = document.querySelector("#editor");
// 移除重复关键词,不影响匹配结果
const keywords = ["DIV", "H1", "P", "HELLO", "<", ">", "/"];

// 核心着色逻辑抽离为独立函数
function highlightKeywords() {
  const str = editor.innerText;
  // 拆分文本为关键词与非关键词片段
  const chunks = str.split(new RegExp(keywords.map(w => `(${w})`).join("|"), "i")).filter(Boolean);
  // 生成带着色标记的HTML
  const markup = chunks.reduce((acc, chunk) => {
    acc += keywords.includes(chunk.toUpperCase())
      ? `<span class="statement">${chunk}</span>`
      : `<span class='other'>${chunk}</span>`;
    return acc;
  }, "");

  // 保存当前光标位置,避免修改HTML后光标错位
  const cursorPos = getCursorPosition(editor);
  
  // 更新编辑器HTML
  editor.innerHTML = markup;
  
  // 恢复光标到原来的位置
  restoreCursorPosition(editor, cursorPos);
}

// 获取contenteditable元素的光标位置
function getCursorPosition(element) {
  let pos = 0;
  const selection = window.getSelection();
  if (selection.rangeCount > 0) {
    const range = selection.getRangeAt(0);
    const preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(element);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    pos = preCaretRange.toString().length;
  }
  return pos;
}

// 恢复光标到指定位置
function restoreCursorPosition(element, pos) {
  const selection = window.getSelection();
  const range = document.createRange();
  range.setStart(element, 0);
  range.collapse(true);
  const nodeStack = [element];
  let currentNode = null;
  let charCount = 0;
  let found = false;

  while (nodeStack.length > 0 && !found) {
    currentNode = nodeStack.pop();
    if (currentNode.nodeType === Node.TEXT_NODE) {
      const textLength = currentNode.length;
      if (charCount + textLength >= pos) {
        range.setStart(currentNode, pos - charCount);
        found = true;
      } else {
        charCount += textLength;
      }
    } else {
      for (let i = currentNode.childNodes.length - 1; i >= 0; i--) {
        nodeStack.push(currentNode.childNodes[i]);
      }
    }
  }

  selection.removeAllRanges();
  selection.addRange(range);
  editor.focus();
}

// 预览功能保持不变
function showPreview() {
  const editorContent = editor.innerText;
  const frame = document.getElementById("preview-window").contentWindow.document;
  document.getElementById("preview-window").srcdoc = editorContent;
  frame.open();
  frame.write(editorContent);
  frame.close();
}

// 页面加载完成后自动初始化
document.addEventListener('DOMContentLoaded', () => {
  highlightKeywords(); // 打开页面立刻着色默认文本
  showPreview(); // 初始化预览内容
  
  // 绑定input事件,覆盖所有内容变化场景(输入、删除、粘贴等)
  editor.addEventListener('input', () => {
    highlightKeywords();
    showPreview();
  });
});

关键修改说明

  1. 抽离核心着色函数:把原来嵌套在keyup事件里的逻辑单独封装,方便页面加载时调用,也利于后续维护
  2. 替换keyup为input事件:input事件能覆盖所有内容变化场景,比仅监听空格键的keyup更可靠
  3. 页面自动初始化:通过DOMContentLoaded事件,页面加载完成后立刻执行着色和预览,打开页面就看到效果
  4. 修复光标定位问题:修改innerHTML会重置光标位置,新增的光标保存/恢复函数保证编辑体验流畅
  5. 清理冗余代码:移除重复关键词,删除无用的内联事件,代码更简洁高效

内容的提问来源于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:37:11