js事件委托

js事件委托是个非常优雅的手法,他借助了事件冒泡的机制,将原本要添加在多个子容器上的事件,添加到了父容器上,这样做可以减少空间的开销,性能会更好

js事件流你需要搞明白,丢一份上期文章,js事件流: 面试官:请问js事件触发过程是怎样的 - 掘金 (juejin.cn)

实现一个情景

css 复制代码
<ul id="ul">
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
</ul>

假设我们想要点击ul列表中每一个li,并且都能打印出对应li的文本值,我们如何实现?

大部分人首先想到的就是拿到li的dom结构数组,然后对他进行遍历,遍历到每个li,就给他单独绑定一个点击事件,如下:

javascript 复制代码
let list = document.querySelectorAll("#ul li");

list.forEach(function(li) {
    li.addEventListener("click", function() {
        console.log(li.innerText)
    })
})

获取一个标签的内容用innerText和innerHTML都可以,二者区别在于innerText只拿到文本内容,而innerHTML还会拿到dom结构

初级程序员就是这样写代码的,中高级不会,如果li一旦多了起来,成百上千个,每一个都绑定一个事件,非常占用空间,非常不优雅。他们就会用到事件委托来处理:

js事件委托

上面的这种情况,我们清楚,li可能会非常多,但是ul只有一个,我们可以借用冒泡机制,点击了li一定会冒泡触发到ul,仅仅给ul绑定点击事件

问题来了,我们拿到ul这个dom结构,点击子容器li可以冒泡触发ul的点击事件,那我们如何清楚点击到了哪一个li呢

首先拿到ul这个dom结构,我们再去看看这个事件参数所携带的属性

javascript 复制代码
ul.addEventListener('click', (e) => {
    console.log(e)
})

事件参数详细描述了所有可以描述该事件的细节,在这里,它包含了ul这个点击事件是从哪一个li来的

我们清楚,事件流有三个阶段,第一阶段就是捕获阶段,从window往目标处走,第二阶段就是到达了目标处,第三阶段就是从目标处往window冒泡,这个事件event就携带了目标属性

我们点击ul中任意一个li,打印的事件对象如下:

我们可以看到事件流的第二阶段的目标target,然后展开它

你会发现,里面就包含了被点击的li的文本值innerHTMLinnerText

所以这里我们用事件委托就可以这样实现:

javascript 复制代码
ul.addEventListener('click', (e) => 
    console.log(e.target.innerHTML) 
})

用vue简单实现

给每个li绑定点击事件如果用vue得话就是如下这样:

先cdn导入vue源码

xml 复制代码
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.3.4/vue.global.js"></script>

然后给一个容器,并写一个代码片段,用v-for循环,并且绑定一个点击事件

xml 复制代码
<div id="app"></div>
<template id="demo">
    <ul>
        <li v-for="(item, index) in list" @click="handle(index)" :key="index">{{item}}</li>
    </ul>
</template>

然后实例一个Vue,并且挂载到app容器上

javascript 复制代码
Vue.createApp({
    template: '#demo',
    data() {
        return {
            list: ['a', 'b', 'c', 'd', 'e']
        }
    },
    methods: {
        handle(i) {
            console.log(this.list[i])
        }
    }
}).mount('#app')

用vue就是这样实现的,如果你有时间看vue源码你就会发现,vue这里就是用到了事件委托,这么有名的框架,人家不可能每个li都给你绑定一个事件。

最后

以上这些知识点就是js事件委托,其实就是借助了js事件流的冒泡事件,把子元素的事件绑定到父元素上,这样可以有效减少空间复杂度,性能更优。下期文章我们再来聊聊js懒加载问题,都是些容易被问到的小面试点

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请"点赞+评论+收藏"一键三连,感谢支持!

本次学习代码已上传至本人GitHub学习仓库:github.com/DolphinFeng...

相关推荐
崔庆才丨静觅10 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅11 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅12 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊12 小时前
jwt介绍
前端