待办列表点击删除按钮误删下方条目且报错 求问题原因解析
报错含义解释
你遇到的Cannot read property 'parentElement' of undefined报错,本质是代码试图读取一个不存在(值为undefined)的对象的parentElement属性,触发报错的就是你点击事件回调里的b[i],触发时b[i]已经是undefined了。
代码存在的问题
- 事件重复绑定:你每次新增待办项时,都会调用
getElementsByClassName('rbutton')获取页面所有已存在的删除按钮,给所有按钮重复绑定点击事件。比如新增3个待办后,第一个删除按钮会被绑定3次点击事件,第二个绑定2次,第三个绑定1次。点击第一个按钮时,多次绑定的事件会依次触发。 - 实时集合特性坑:
getElementsByClassName返回的是动态实时的HTML集合,页面DOM变化时集合内容会同步更新。第一次点击事件触发删除对应待办后,集合长度会直接缩短,后续事件触发时循环变量i已经超过了集合的最新长度,b[i]就变成undefined,同时前面几次有效触发还会顺次删除后续的待办项,就是你遇到的“删除该条目下方所有待办项”的问题。 - 循环变量闭包问题:你在for循环的回调里直接使用循环变量
i,等点击事件实际触发时,循环已经执行完毕,i的值已经是循环结束时的最大值,也会导致b[i]取到undefined。
修复方案
最简单的修复方式是每次新增待办时,只给当前新增的删除按钮绑定事件,同时用this指向触发事件的按钮本身,避免使用实时集合和循环变量:
'use strict' const buttonclick = document.getElementById('button') const list = document.getElementById('lists') const a = "<span><button class = 'rbutton'>X</button></span>" //list-item button const clickhandler = () => { const text = document.getElementById('text') if(text.value != ''){ let Newdiv = document.createElement('div') Newdiv.innerHTML = text.value + a list.appendChild(Newdiv) // 仅获取当前新增待办里的删除按钮绑定事件 const currentDelBtn = Newdiv.querySelector('.rbutton') currentDelBtn.addEventListener('click', function(){ // this指向当前点击的删除按钮 this.parentElement.parentElement.remove(); }) text.value = '' } } buttonclick.addEventListener('click', clickhandler)
更推荐使用事件委托的方案,直接给待办列表父容器绑定统一的点击事件,不需要每次新增待办都重复绑定,性能和可维护性更好:
'use strict' const buttonclick = document.getElementById('button') const list = document.getElementById('lists') const a = "<span><button class = 'rbutton'>X</button></span>" //list-item button // 父容器统一处理所有删除按钮的点击事件 list.addEventListener('click', function(e) { // 判断点击的元素是不是删除按钮 if(e.target.classList.contains('rbutton')) { e.target.parentElement.parentElement.remove(); } }) const clickhandler = () => { const text = document.getElementById('text') if(text.value != ''){ let Newdiv = document.createElement('div') Newdiv.innerHTML = text.value + a list.appendChild(Newdiv) text.value = '' } } buttonclick.addEventListener('click', clickhandler)
内容的提问来源于stack exchange,提问作者Jasmeet
相关产品推荐
相关产品推荐

