如何简单重置DOM解决JS单词猜谜游戏重置后的各类异常问题?
问题根因与修复代码
三个问题的核心都来自状态重置不彻底、事件重复绑定、内联样式优先级过高:
- 问题1:每次重置调用
ans()时会给所有字母按钮重复绑定点击事件,多次绑定后点击一次按钮会触发多次回调,同时部分按钮移除事件的逻辑混乱,导致无法点击 - 问题2:直接设置按钮的内联背景色优先级高于CSS的hover规则,导致hover失效
- 问题3:事件重复绑定后,单次点击会触发多次错误判断逻辑,导致尝试次数异常扣减,同时未清理的游戏结束定时器也可能在重置后异常修改次数值
第一步:新增CSS类(替换原内联改背景的逻辑)
/* 加到你的样式文件里 */ .letter-btn.disabled { background-color: grey; pointer-events: none; }
用类控制禁用状态,不会覆盖hover样式,同时自动禁止点击,不需要手动移除/绑定事件。
第二步:修改后的完整JS代码
// 词库 const words = [ "planet", "stars", "astroid", "moon", "satilite", "orbit", "universe", "umbra", "lunar", "space", "astronomy", "eclipse", "nebula", "mars", "meteorite"]; // 已猜字母数组 let myGuesses = []; // 通用变量 let wordSpace = " - "; let guess = " "; let space; // 单词的空格数量 // 分数相关 let tries = 10; let counter; // 存储定时器ID,避免重置后旧定时器触发 let gameEndTimer = null; // 取随机词下标 let index = Math.floor(Math.random() * words.length); // 游戏启动函数 function play(isReset = false) { // 只在第一次进入游戏弹提示,重置的时候不重复弹 if (!isReset) { let userInput = prompt(`你想要玩太空人猜词游戏吗?(Y/N)`, "Y"); } console.log(words[index]); for (let i = 0; i < words[index].length; i++) { let div = document.createElement("div"); div.classList.add("letters"); div.innerHTML = " - "; document.querySelector(".word-space").append(div); } } // 点击事件处理函数,点击后将按钮标记为已用 let handleclick = (e) => { e.target.classList.add('disabled'); console.log(e.target.innerHTML); myGuesses.push(e.target.innerHTML); console.log(myGuesses); console.log(words[index].includes(e.target.innerHTML)); if (words[index].includes(e.target.innerHTML)) { document.querySelector(".word-space").innerHTML = " "; for (let i = 0; i < words[index].length; i++) { let div = document.createElement("div"); div.classList.add("letters"); if (myGuesses.includes(words[index][i])) { div.innerHTML = words[index][i]; } else { div.innerHTML = " - "; } document.querySelector(".word-space").append(div); } getNumOfTries(); } else { tries--; getNumOfTries(); } }; function ans() { const buttons = document.querySelectorAll("button.letter-btn"); buttons.forEach((button) => { // 先移除旧的事件,避免重复绑定 button.removeEventListener("click", handleclick); button.addEventListener("click", handleclick); }); } ans(); function getNumOfTries() { console.log(tries); const showTries = document.querySelector("#myTries"); showTries.innerHTML = " 你还有 " + tries + " 次机会"; // 先清掉之前的定时器 if (gameEndTimer) clearTimeout(gameEndTimer); if (tries < 1) { gameEndTimer = setTimeout(() => { prompt(`你想要再试一次吗?(Y,N)`, "Y"); showTries.innerHTML = "你输了!"; }, 2000); } Array.from(document.querySelectorAll(".letters")).forEach((letter) => { console.log(letter.innerHTML); }); if ( tries > 0 && Array.from(document.querySelectorAll(".letters")).every( (letter) => letter.innerHTML !== " - " ) ) { gameEndTimer = setTimeout(() => { alert(`你赢了!`); showTries.innerHTML = "你赢了!"; }, 1000); } } // 游戏重置逻辑 let tryAgain = document.querySelector(".Try-Again"); tryAgain.addEventListener("click", () => { // 清旧定时器 if (gameEndTimer) clearTimeout(gameEndTimer); myGuesses = []; tries = 10; wordSpace = " - "; index = Math.floor(Math.random() * words.length); document.querySelector(".word-space").innerHTML = ""; let showTries = document.querySelector("#myTries"); showTries.innerHTML = "再试一次"; let buttons = document.querySelectorAll("button.letter-btn"); buttons.forEach((button) => { // 移除禁用类,恢复默认样式和点击能力 button.classList.remove('disabled'); }); ans(); // 重置的时候传参数,不重复弹初始提示 play(true); }); play();
注意:请给所有字母按钮加上
letter-btn类,避免重置逻辑影响到.Try-Again重置按钮。
内容的提问来源于stack exchange,提问作者Tamara
相关产品推荐
相关产品推荐

