鼠标悬停段落元素时字符随机消失问题求助
问题解决:鼠标悬停时字符随机消失的修复
问题分析
你遇到的字符随机消失问题,核心原因有两个:
- 段落的
mouseover事件会重复触发highlight函数,每次触发都会重新将文本拆分为字符并生成新的span替换原innerHTML,过程中索引处理错误导致字符丢失; - 单词处理逻辑中固定循环6次取字符,未考虑数组边界和实际文本结构,会导致越界取到
undefined,最终显示为空。
解决方案
关键修改思路
- 提前构建带span的DOM结构:在
fillParagraph生成文本时直接用span包裹字符和单词,避免后续重复修改innerHTML; - 用CSS伪类实现高亮:替换JS绑定的
mouseover/mouseout事件,用:hover伪类实现高亮,更稳定高效; - 修复单词识别逻辑:正确识别连续的字母序列作为单词,而非固定截取6个字符。
修正后的核心代码
const garbage = ["`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "-", "_", "=", "+"]; // 移除原单词里的前置空格,避免干扰识别 const wordBank = ["jujube", "muzzle", "puzzle", "whizzo", "jimply", "jinxed", "fezzes", "queazy"]; const numOfRows = 8; const password = wordBank[randomNum(0, wordBank.length)]; function fillText() { fillParagraph("left-p"); fillParagraph("right-p"); } function fillParagraph(pId) { let spanElements = []; let wordPos = []; let counter = 0; // 生成3个不重叠的单词位置 while (counter < 3) { let validPos = false; while (!validPos) { validPos = true; const randomNumber = randomNum(0, (12 * numOfRows) - 6); for (let pos of wordPos) { if (Math.abs(randomNumber - pos) <= 6) { validPos = false; break; } } if (validPos) { wordPos.push(randomNumber); counter++; } } } // 构建每个位置的元素:单词或符号 for (let i = 0; i < numOfRows * 12; ) { // 每12个字符换行 if (i !== 0 && i % 12 === 0) { spanElements.push(document.createElement('br')); } // 当前位置是单词起始点 if (wordPos.includes(i)) { const word = wordBank.shift(); const wordSpan = document.createElement('span'); wordSpan.className = 'word'; wordSpan.textContent = word; spanElements.push(wordSpan); // 跳过单词占用的位置 i += word.length; } else { // 生成单个符号的span const charSpan = document.createElement('span'); charSpan.className = 'char'; charSpan.textContent = garbage[randomNum(0, garbage.length - 1)]; spanElements.push(charSpan); i++; } } // 渲染到页面 const paragraph = document.getElementById(pId); paragraph.innerHTML = ''; spanElements.forEach(el => paragraph.appendChild(el)); } function randomNum(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
对应的CSS样式:
/* 单个符号和单词的高亮效果 */ .char:hover, .word:hover { background-color: yellow; } /* 保持排版整齐 */ #left-p, #right-p { white-space: pre-line; font-family: monospace; line-height: 1.2; }
修改说明
- DOM构建时机调整:在
fillParagraph中直接创建span元素,一次性添加到段落,彻底避免重复修改innerHTML导致的字符丢失; - 单词位置生成优化:改用while循环生成3个不重叠的单词位置,逻辑更清晰,避免原代码中循环次数冗余的问题;
- CSS高亮替代JS事件:用
:hover伪类实现高亮,无需绑定大量事件,避免事件重复触发的冲突; - 修复单词处理逻辑:直接使用单词本身的长度跳过位置,避免固定6次循环的越界问题,同时清理了原单词数组中的前置空格,保证文本结构正确。
内容的提问来源于stack exchange,提问作者someCoder21
相关产品推荐
相关产品推荐

