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...

相关推荐
GIS开发特训营1 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood27 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端28 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_8532 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
程序猿进阶33 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
还是大剑师兰特1 小时前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_748248941 小时前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235611 小时前
从零开始学前端之HTML(三)
前端·html