JS点击提交按钮追加选中项到数组报null读取length错误咨询
问题说明
你不需要特意更换事件绑定方式,不管是onclick还是addEventListener都能实现需求,现在报错的核心是代码里有4处明显的写法错误:
- 提交按钮选择器写错:
document.querySelector('modal-btn')是匹配<modal-btn>自定义标签,你的提交按钮是class为modal-btn的input,选择器漏了类名前缀.,根本没拿到DOM元素,给null绑定点击事件就会抛出空值相关的错误。 - 选中项选择器写错:
getElementsByClassName方法只接收纯类名参数,不支持传入.btn.button-focus这种CSS复合选择器;而且你在页面初始化时就给results赋值,后续用户点击选择按钮时这个变量不会同步更新,永远拿不到最新的选中项。 - 类名判断逻辑错误:遍历按钮classList判断是否有
button-focus类时,只要遍历到的最后一个类名不是目标类,就会把isPresent重置为false,哪怕元素本身带了选中类也会判断错误,直接用classList自带的contains方法就行,不用手动遍历。 - 提交逻辑错误:循环里push的是整个
results集合,不是单个选中项的值,就算能拿到元素也存不对内容。
修正后的完整JS代码
const container = document.getElementById('my_dataviz'); const optionArray = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"] let selectCount = 0; // 生成选项按钮 optionArray.forEach(element => { const button = document.createElement("button"); button.className = "btn"; button.id = element; button.value = element; button.type = "button"; button.textContent = element; container.appendChild(button); }); // 绑定选项按钮点击逻辑 const btnList = document.getElementsByClassName("btn"); for (let i = 0; i < btnList.length; i++) { btnList[i].addEventListener("click", function() { console.log("Clicked Button index: " + i); // 直接用contains判断类名,避免遍历判断的逻辑错误 const isSelected = this.classList.contains("button-focus"); if (isSelected) { this.classList.remove("button-focus"); selectCount -= 1; // 取消选中后恢复所有按钮可点 document.querySelectorAll('.btn').forEach(item => { item.disabled = false }) } else { this.classList.add("button-focus"); selectCount += 1; // 选满3个后禁用未选中的按钮 if (selectCount > 2) { document.querySelectorAll('.btn').forEach(item => { if (!item.classList.contains('button-focus')) item.disabled = true }) } } }) } const dataResults = [] // 修正选择器,选中提交按钮 const submit_button = document.querySelector('.modal-btn') submit_button.onclick = function() { // 点击提交时再实时获取最新的选中按钮,不要提前缓存 const selectedBtns = document.querySelectorAll('.btn.button-focus') dataResults.length = 0; // 清空之前的结果避免重复提交 selectedBtns.forEach(btn => { dataResults.push(btn.value) }) console.log('提交的选中项:', dataResults) }
补充说明
- 如果后续要给同一个元素绑定多个点击事件,再换
addEventListener就行,单事件场景下onclick完全够用。 - 拿DOM元素的时候一定要注意选择器格式:类名前要加
.,id前加#,getElementsByClassName/getElementsByTagName这类方法不要传带前缀符号的选择器。 - 会动态变化的DOM状态不要在页面初始化时就缓存,触发对应逻辑的时候重新查询才能拿到最新结果。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

