给DOM元素添加对象属性并修改:井字棋开发遇阻求助
井字棋DOM属性更新失效的修复方案
问题出在哪
你这段代码有两个关键问题:
- 没给每个盒子初始化
avail和mark属性,直接在点击事件里修改,导致初始状态下这些属性根本不存在,后续更新自然不会生效; - 直接给DOM元素挂自定义属性容易和原生属性冲突,浏览器对这类非标准属性的处理也不稳定。
修复代码
先初始化所有盒子状态
推荐用HTML5标准的dataset属性(带data-前缀)来存自定义状态,彻底避免冲突:
const allBoxes = [b1,b2,b3,b4,b5,b6,b7,b8,b9]; // 给每个盒子设置初始状态 allBoxes.forEach(box => { box.dataset.avail = "true"; // dataset的值都是字符串,判断时转布尔就行 box.dataset.mark = "null"; });
绑定点击事件并完善逻辑
点击时先判断是否可点击,再执行落子,用this指向当前被点击的盒子(比循环变量b更可靠):
for (let b of allBoxes){ b.addEventListener("click", function(){ // 先检查是否能落子 if (this.dataset.avail === "true") { this.innerText = "X"; this.dataset.mark = "X"; this.dataset.avail = "false"; // 这里可以加切换玩家、判断胜负的逻辑 } }); };
另一种优化思路:状态和DOM分离
如果不想用dataset,可以单独用一个对象存所有盒子的状态,把数据和DOM元素分开管理,更清晰:
const allBoxes = [b1,b2,b3,b4,b5,b6,b7,b8,b9]; // 用对象存储每个盒子的状态,key是盒子id const boxStates = {}; allBoxes.forEach(box => { boxStates[box.id] = { avail: true, mark: "null" }; }); // 绑定点击事件 for (let b of allBoxes){ b.addEventListener("click", function(){ const state = boxStates[this.id]; if (state.avail) { this.innerText = "X"; state.mark = "X"; state.avail = false; } }); };
内容的提问来源于stack exchange,提问作者SparklingLemonWater
相关产品推荐
相关产品推荐

