JS 事件委托绝了!1 次绑定搞定所有按钮点击,告别 JavaScript 重复事件绑定
你写 JS 的时候,是不是遇到过 “列表里 10 个按钮,每个都要加点击事件” 的情况?比如做一个待办清单,每个待办项后面都有 “删除” 按钮,你可能会用 for 循环遍历所有按钮,逐个绑定 onclick 事件 —— 但要是后来又新增了待办项,新的 “删除” 按钮点了没反应,还得再绑一次事件,特别麻烦?
其实解决这问题不用反复绑定事件,用 JS 的 “事件委托” 一招就能搞定,不管是 10 个按钮还是 100 个按钮,甚至后来新增的按钮,只要绑一次事件就行,今天咱们就把这事说透,代码少还实用。
首先得搞明白,事件委托到底是啥?你可以把它想成 “公司收快递”:要是每个员工都自己等快递,快递员得一个个找,效率低;但要是让前台统一收,员工再去前台拿,就省事多了 —— 这里的 “前台” 就是父元素,“员工” 是子元素(比如按钮),“快递” 就是点击事件。简单说,就是把原本要绑在子元素上的事件,绑到它们的父元素上,让父元素 “代收” 事件,再判断该处理哪个子元素的事件。
这背后靠的是 JS 的 “事件冒泡” 机制:当你点击子元素(比如按钮)时,事件会从子元素往上 “冒”,先到父元素,再到祖父元素,直到 html 根元素。就像你在教室里扔了个纸团,声音会从你座位传到前排,再传到讲台 —— 父元素就是能 “听到声音” 的前排,所以能知道是哪个子元素触发了事件。
举个实际例子,比如一个待办列表,HTML 结构是这样的:
用事件委托就不一样了,咱们把事件绑在父元素.todo-list 上:
const todoList = document.querySelector ('.todo-list');
todoList.onclick = function (e) {
//e.target 就是触发事件的元素(可能是按钮,也可能是 li 里的文字)
if (e.target.classList.contains ('delete-btn')) {
// 确认是删除按钮才执行操作
e.target.parentElement.remove ();
}
};
就这几行代码,不管原来有多少个删除按钮,还是后来新增多少个,点击都能用 —— 因为父元素.todo-list 一直在,事件绑在它身上,只要点击的是它里面的.delete-btn,就能被识别到。
这里有个新手必踩的坑,小索奇得提醒你:别搞混 e.target 和 e.currentTarget。e.target 是 “实际触发事件的元素”(比如你点的删除按钮),e.currentTarget 是 “绑定事件的元素”(这里的.todo-list)。我之前见过有人把 e.currentTarget 当成按钮来用,结果怎么都删不了待办项 —— 所以你判断的时候,一定要用 e.target,看它是不是你要处理的元素。
还有个注意点:父元素要选 “稳定的”,也就是不会被删除或替换的元素。比如你要是把事件绑在上,而可能会被删除,那删除后事件就没了;但.todo-list 一般不会被删,所以选它当父元素最稳妥。要是页面里没有更外层的稳定父元素,甚至可以绑在 document 上,不过尽量别这么做,因为 document 范围太大,可能会和其他事件冲突。
小索奇认为,事件委托不只是省代码,还能提升性能。比如你有 1000 个列表项,每个都绑事件,会创建 1000 个事件处理函数;但用事件委托,只需要 1 个处理函数,内存占用少多了 —— 尤其是在移动端,性能差异会更明显。
你可以现在就试试改造代码:把之前用循环绑定事件的代码,改成事件委托的写法,再新增几个子元素,看看点击是不是还能用。要是遇到问题,比如 “点了按钮没反应”,先检查 e.target 的判断条件对不对,比如是不是把 class 名写错了(比如写成了 deleteBtn 而不是 delete-btn),或者父元素选得不对 —— 评论区可以说说你试的结果,咱们一起找问题。
另外,事件委托不止能用在 click 事件上,像 mouseover、mouseout、keydown 这些事件也能用。比如你想给列表项加 “鼠标 hover 时变色” 的效果,不用给每个绑 mouseover,绑在父元素上,判断 e.target 是,再改它的样式就行,逻辑和点击事件一样。
我是【即兴小索奇】,点击关注,后台回复 领取,获取更多相关资源
更多推荐
所有评论(0)