addEventListener更新全局变量出现滞后赋值问题求助
问题描述
此前通过addEventListener监听下拉菜单变更来设置全局变量一直正常运行,但复用该逻辑到新菜单时出现异常:全局变量需到第三次变更菜单选项才开始更新,且更新的值为上一次选中的选项值。即便setTestValue()函数已被调用,事件监听器似乎到第三次菜单变更才生效。具体表现如下:
| 选中的菜单值 | valueStored | 函数调用次数 |
|---|---|---|
| 初始值 | Default | 1 |
| 9 | Default | 2 |
| 8 | Default | 3 |
| 7 | 8 | 4 |
| 6 | 7 | 5 |
相关代码:
<!-- test menu code --> <select id="testMenu" onchange="setTestValue()" class="menu shadow"> <option value="9999" selected>9999</option> <option value="9">9</option> <option value="8">8</option> <option value="7">7</option> <option value="6">6</option> <option value="5">5</option> <option value="4">4</option> <option value="3">3</option> <option value="2">2</option> <option value="1">1</option> </select>
// test menu javascript var selected; var stored = "Default"; function setTestValue() { selected = document.getElementById("testMenu"); selected.addEventListener("change", function handleChange(event) { stored = Number(event.target.value); }); console.log("stored is: " + stored); console.log("stored type: " + typeof stored); }
问题原因
- 重复绑定事件监听器:每次下拉菜单触发
onchange都会调用setTestValue(),而每次调用都会给菜单新增一个change事件监听器。第一次调用(从初始值选9):绑定第一个监听器,但该监听器要等下一次change事件才会触发;第二次调用(选8):绑定第二个监听器,此时第一个监听器仍未执行;第三次调用(选7):绑定第三个监听器,同时第一个监听器触发,将stored设为上一次选中的8,这就导致第三次变更后才看到更新且值为上一次的选项。 - 日志打印时机错误:
console.log在绑定监听器后立即执行,此时监听器还未触发,打印的始终是旧值。
修复方案
提供两种可行的修复方式:
方式一:移除onchange属性,单次绑定监听器
删除HTML中的onchange="setTestValue()",在脚本中仅绑定一次监听器,同时在监听器内处理变量更新与日志打印:
<!-- 修改后的HTML --> <select id="testMenu" class="menu shadow"> <option value="9999" selected>9999</option> <option value="9">9</option> <option value="8">8</option> <option value="7">7</option> <option value="6">6</option> <option value="5">5</option> <option value="4">4</option> <option value="3">3</option> <option value="2">2</option> <option value="1">1</option> </select>
// 修改后的JS var stored = "Default"; // 页面加载完成后绑定一次监听器 document.addEventListener('DOMContentLoaded', function() { const testMenu = document.getElementById("testMenu"); testMenu.addEventListener("change", function handleChange(event) { stored = Number(event.target.value); console.log("stored is: " + stored); console.log("stored type: " + typeof stored); }); });
方式二:保留onchange,直接获取当前选中值
若需保留onchange="setTestValue()",可直接在函数内获取当前选中值,无需额外绑定change监听器:
var stored = "Default"; function setTestValue() { const testMenu = document.getElementById("testMenu"); // 直接获取当前选中的值 stored = Number(testMenu.value); console.log("stored is: " + stored); console.log("stored type: " + typeof stored); }
内容的提问来源于stack exchange,提问作者Richard Cosgrove
相关产品推荐
相关产品推荐

