HTML重复使用相同span id致JS取值异常的原因与解决方法
问题根因
你已经排查到核心问题:HTML规范要求id属性在整个文档中全局唯一,调用document.getElementById()获取元素时,只会返回匹配到的第一个DOM节点。你当前代码中战士/弓箭手商店、法师商店两个容器内,重复使用了大量相同id(包括分类容器的view1、所有商品对应的价格/库存span的id),JS执行赋值逻辑时永远只会选中战士/弓箭手商店内的元素,法师商店内的同id节点不会被访问到,自然无法写入数据。
零数据重构解决方案
完全不需要重写已有的商品数据对象,只需要做两处小改动即可:
- 调整HTML属性:保留两个职业商店根容器的现有唯一id(战士/弓箭手为
Warrior_Archer's_Other、法师为Mage's_Other,这两个不需要改),把两个容器内部所有重复的id属性全部替换为同名class即可。比如原来的<div id="view1">改成<div class="view1">,原来的<span id="Boxers.Value">0</span>改成<span class="Boxers.Value">0</span>,所有商品的价格、库存span都按这个规则替换。
修改后的HTML结构示例如下:<div class="OtherStuff_Container" id="o_shop" style="display: none;"> <div id="OtherStuff_Banner"> <p>Other Stuff</p> </div> <div class="Shop_OtherStuff" id="Warrior_Archer's_Other" style="display: none;"> <div class="view1"> <p>Clothing:</p><br /> <p>9.) Boxers: Price: $<span class="Boxers.Value">0</span>   Amount Left: <span class="Boxers.AmountOf">0</span></p> <!-- 其余衣物商品同理将span的id替换为class --> </div> <div class="view1"> <p>Potions:</p><br /> <!-- 药水类商品同理将span的id替换为class --> </div> </div> <div class="Shop_OtherStuff1" id="Mage's_Other" style="display: none;"> <div class="view1"> <p>Clothing:</p><br /> <p>10.) Boxers: Price: $<span class="Boxers.Value">0</span>   Amount Left: <span class="Boxers.AmountOf">0</span></p> <!-- 其余衣物商品同理将span的id替换为class --> </div> <div class="view1"> <p>Potions:</p><br /> <!-- 药水类商品同理将span的id替换为class --> </div> </div> </div> - 调整JS元素查找逻辑:不要全局直接通过id查找元素赋值,先根据用户当前选择的职业定位到对应的商店根容器,再在这个容器范围内查找对应class的元素完成赋值即可,原有商品数据的变量、取值逻辑完全不需要改动。
逻辑示例如下:// 先定位当前职业对应的商店容器 const activeShop = userSelectedClass === 'mage' ? document.getElementById("Mage's_Other") : document.getElementById("Warrior_Archer's_Other"); // 所有商品赋值操作都在当前激活的商店容器内查找元素,不会串到另一个商店的内容 activeShop.querySelector('.Boxers.Value').textContent = shopData.Boxers.price; activeShop.querySelector('.Boxers.AmountOf').textContent = shopData.Boxers.stock; // 其余所有商品的赋值逻辑只需要把原来的全局getElementById,替换成activeShop.querySelector加对应class选择器即可
这种改法总改动量极低,完全不需要重构你已经写好的商品数据、数值逻辑,改完两个职业的商店就都能正常渲染数据了,后续如果要加新职业的商店也可以按同样逻辑扩展,不会出现id冲突问题。
内容的提问来源于stack exchange,提问作者Joseph Hogue
相关产品推荐
相关产品推荐

