那些被你忽略的事件委托场景

237 阅读2分钟

之前我只会在多个子元素的父级元素上绑定点击事件的时候用到事件委托,直到遇到了一个难缠的Bug......还是再看看好好看看这部分知识吧,有时候就是遇到了才会着重学习某部分

前言

在JavaScript中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多。首先,每个函数都是对象,都占用内存空间,对象越多,性能越差。其次,为指定事件处理 程序所需访问DOM的次数会先期造成整个页面交互的延迟。只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。

“过多事件处理程序”的解决方案是使用事件委托。事件委托利用事件冒泡,可以只使用一个事件 处理程序来管理一种类型的事件。例如,click事件冒泡到document。这意味着可以为整个页面指定一个onclick 事件处理程序,而不用为每个可点击元素分别指定事件处理程序。

一些简单的例子

假设,拉起相册选择图片的页面,百上千个图片的图库,分为不同的子组件展示,且点击任意图片之后放大该图片

组件一:
<div class="gallery" @click="transScalePic1>
    <img v-for="(image, index) in images" :key="index" :src="image"  />
</div>
组件二:
<div class="gallery" @click="transScalePic2>
    <img v-for="(image, index) in images" :key="index" :src="image"  />
</div>


// 在父组件委托监听函数
document.getElementByClassName('gallery').addEventListener('click', function(event) {
   if (event.target.tagName === 'IMG') {
       // 模拟图片放大操作
       event.target.style.width = '400px';
       event.target.style.height = '400px';
   }
})


再例如,阻止当前页面的跳转行为

思路:通过事件委托,监听页面上的所有click事件,如果是a链接,则取消事件

// 为页面的父容器添加点击事件监听
document.getElementById('container').addEventListener('click', function(event) {
   // 如果点击的是 a 链接
   if (event.target.tagName === 'A') {
     event.preventDefault();  // 阻止 a 链接的默认跳转行为
   }
});
以后再问爷孙组件通信得加上这一条

在子组件提交表单之后,自定义一个“submited”事件,同时在父组件中将监听“submited”委托在顶层document中,也可以避免一层层透传emit

子组件
const submited = () => { 
    document.dispatchEvent(new Event('submited')) 
}

父组件
document.addEventListener('submited', (event) => { console.log('event', event) })
  
对页面的点击事件统一操作

假设页面中展示了许多色块子组件,要求鼠标点击之后复制该信息并传递给顶层父组件,由父组件弹出提示

色块组件一:
<div class="colorBlock" @click="clickCurrentBlock1()">
    <div v-for="(item, index) in list" :key="index" />
</div>
色块组件二
<div class="colorBlock" @click="clickCurrentBlock2()">
    <div v-for="(item, index) in list" :key="index" />
</div>

function handleClick(event) {
   const color = window.getComputedStyle(event.target).backgroundColor;
   alert(`已复制颜色:${color}`);
}

// 为色块父组件添加点击事件监听
document.getElementByClassName('colorBlock').addEventListener('click', handleClick)