Javascript文本着色问题:输入完成后立即着色而非按空格触发
问题:输入目标单词后无法立即着色,仅空格键触发
我用JavaScript实现文本着色时遇到问题:已配置需要着色的关键词(比如HELLO),但只有按下空格键时才会给单词上色,输入完单词的最后一个字母后不会立即变色。希望输入完目标单词(比如HELLO的最后一个字母O)时就立刻着色,不用等空格。
问题出在changeColor()函数里的键盘抬起事件(keyup)和空格判断逻辑,我尝试移除相关监听代码后功能直接失效,刚接触JS搞不定,附上代码:
解决方案
核心问题是原代码只在空格键抬起时才调用着色函数,现在改成每次按键抬起都触发着色,同时修复修改DOM后光标错位的问题。
修改要点:
- 移除
changeColor()里的空格判断条件,让所有keyup事件都触发着色 - 在
applyColoring函数中新增光标位置保存与恢复逻辑,避免修改HTML后光标乱跑 - 删掉编辑器上的
onchange="changeColor()"冗余属性
修改后的完整代码
index.html
<div id="editor" contenteditable="true" oninput="showPreview();"><h1>This is a Heading</h1> <p>This is a paragraph.</p> </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
相关产品推荐
相关产品推荐

