
本文讲解如何将 HTML 编辑器中关键词(如 HELLO、)的着色逻辑从“按空格后触发”升级为“输入完成即实时高亮”,通过改用 input 事件替代 keyup + space 判断,并优化 DOM 操作与光标恢复逻辑。
本文讲解如何将 html 编辑器中关键词(如 `hello`、`
`)的着色逻辑从“按空格后触发”升级为“输入完成即实时高亮”,通过改用 `input` 事件替代 `keyup + space` 判断,并优化 dom 操作与光标恢复逻辑。
在构建类代码编辑器的富文本区域(contenteditable)时,一个常见需求是:对预设关键词(如 HTML 标签、自定义指令)进行即时语法高亮。原始实现依赖 keyup 事件监听空格键(keyCode === 32),导致用户必须输入完整单词(如 HELLO)后再敲空格,高亮才生效——这严重违背直觉,也影响编码体验。
核心改进:用 input 事件替代 keyup + space
input 事件在 <div contenteditable> 中任何内容变更(包括输入、粘贴、删除、撤销)后立即触发,且无需判断按键类型,天然适配“所见即所得”的实时着色需求。我们只需移除原 <code>changeColor() 中冗余的事件监听器注册逻辑,将其改造为纯函数,并在 oninput 属性中直接调用:
<div id="editor" contenteditable="true" oninput="changeColor(); showPreview();"> <h1>This is a Heading</h1> <p>This is a paragraph.</p> </div>
同时,changeColor() 函数需精简重构:不再监听事件,而是直接获取编辑器元素并执行着色,同时确保光标位置不因 innerHTML 重写而丢失:
function changeColor() {
const editor = document.getElementById("editor");
applyColoring(editor);
// 恢复光标至末尾(关键!避免输入中断)
const range = document.createRange();
const sel = window.getSelection();
range.selectNodeContents(editor);
range.collapse(false); // collapse to end
sel.removeAllRanges();
sel.addRange(range);
editor.focus();
}applyColoring() 的健壮性增强
原函数存在重复关键词(如 "DIV", "DIV")、大小写敏感缺陷及未处理空格/换行导致的匹配断裂。优化后:
- 去重并精简关键词数组;
- 使用
RegExp的i标志实现不区分大小写匹配; -
split()后filter(Boolean)清理空字符串; - 严格比对
chunk.toUpperCase()与关键词,避免部分匹配(如"HE"误匹配"HELLO");
function applyColoring(element) {
const keywords = ["DIV", "H1", "P", "HELLO", "<", ">", "/"];
const text = element.innerText;
// 构建分隔正则:匹配任意关键词(不区分大小写)
const regex = new RegExp(keywords.map(k => `(${k})`).join("|"), "gi");
const chunks = text.split(regex).filter(Boolean);
let markup = "";
chunks.forEach(chunk => {
// 精确匹配:转为大写后检查是否在关键词列表中
if (keywords.includes(chunk.toUpperCase())) {
markup += `<span class="statement">${chunk}</span>`;
} else {
markup += `<span class="other">${chunk}</span>`;
}
});
element.innerHTML = markup;
}注意事项与最佳实践
- ✅ 避免
onchange陷阱:contenteditable元素不触发change事件,原onchange="changeColor()"无效,应全部移除; - ✅
showPreview()安全性提升:使用data:text/htmlURL 方式加载 iframe 内容,规避document.write()在已加载文档中的潜在错误; - ⚠️ 性能提醒:高频
input触发下,若关键词量极大或文本极长,可引入防抖(debounce)——但本例中轻量级着色无需过度优化; - ⚠️ 样式隔离:
.other类需在 CSS 中明确定义(如color: inherit;),否则可能继承异常颜色; - ? 安全警告:生产环境切勿直接将用户输入写入
srcdoc或document.write(),需做 HTML 实体转义或使用DOMPurify等库防范 XSS。
最后,初始化时务必调用 changeColor() 和 showPreview() 一次,确保页面加载后即呈现正确样式与预览。整套方案简洁、可靠,真正实现“敲完最后一个字母,高亮立刻浮现”的专业编辑体验。

















