前言
在开发 Vue 项目时,我们经常需要处理大量的点击事件。为每个可点击的元素单独添加事件监听器不仅会增加代码的复杂度,还会降低性能。事件委托是一种有效的优化方式,它可以显著减少事件监听器的数量,提高代码的可维护性和执行效率。我们通过一个实际示例,详细讲解如何在 Vue 项目中使用事件委托。简单记录一下
一. 事件委托定义
VueJS中的事件委托是一种优化事件处理和提升性能的技术,它允许你在一个父元素上监听事件,而不是在每个子元素上单独绑定事件处理器。这种做法基于JavaScript 的事件冒泡机制,即在DOM树中,事件会从最深层的节点开始向上冒泡,直到到达document根节点。
二. HTML 内容结构
1. 首先,看下 HTML 部分:
<div class="homeView_box"><div class="iconInside_box" @click="choseIconInside"><img src="@/assets/sxzy/1.png" class="cmCt img1" data-action="moveUp" /><imgsrc="@/assets/sxzy/2.png"class="cmCt img2"data-action="moveDown"/><imgsrc="@/assets/icons/home3.png"class="cmCt img3"data-action="mainView"@click="choseHomeIcon"/><imgsrc="@/assets/sxzy/3.png"class="cmCt img4"data-action="moveLeft"/><imgsrc="@/assets/sxzy/4.png"class="cmCt img5"data-action="moveRight"/></div></div>
2. 以上部分代码,我们写了一个父级 div 容器 .iconInside_box,其中包含5个 img 元素,每个 img 元素代表一个可点击的图标。其中:
- @click=“choseIconInside”,在父级容器上绑定点击事件监听器。
- data-action,每个 img 元素都有一个data-action 属性,用于标识点击时要执行的动作。
三. 事件逻辑函数
1. 事件触发时,事件委托的处理函数;这里我们有一个包含多个图标的 div 容器,每个HTML元素图标,有不同的点击操作,请看以下:
choseIconInside(e) {const action = e.target.getAttribute("data-action");if (action) {switch (action) {case "moveUp":console.log("向上移动");// 实现向上移动的逻辑this.viewer.camera.moveUp(10);break;case "moveDown":console.log("向下移动");// 实现向下移动的逻辑this.viewer.camera.moveDown(10);break;case "moveLeft":console.log("向左移动");// 实现向左移动的逻辑this.viewer.camera.moveLeft(10);break;case "moveRight":console.log("向右移动");// 实现向右移动的逻辑this.viewer.camera.moveRight(10);break;case "mainView":console.log("主视角图");let _this = this;this.viewer.camera.flyTo({destination: this.Cesium.Cartesian3.fromDegrees(118.879624,32.036791,10),orientation: {// 设置相机的默认方向(heading),此处为朝向东南方向heading: this.Cesium.Math.toRadians(238),// 设置相机的俯仰角(pitch),此处为略微向下看pitch: this.Cesium.Math.toRadians(-15),// 设置相机的滚转角(roll),此处为不滚转roll: 0.0,},duration: 2,complete: function () {_this.viewer.camera.zoomOut(200); // 在飞行动画完成后缩小场景},});break;default:console.log("未知动作");}}},},
2. 以上代码我们展示了一个事件处理器函数 choseIconInside
,它用于响应用户在界面中对某些图标或按钮的点击操作。该函数主要实现了以下功能:
1. 读取data-action属性:
- 当事件触发时,函数通过事件对象 e.target 获取被点击元素上的 data-action 属性值。这个属性是用来区分不同图标或按钮的功能的。
2. 根据data-action执行不同操作:
- 使用 switch 语句根据 data-action 的值执行相应的逻辑。
- "moveUp" 和 "moveDown":控制相机沿垂直轴向上或向下移动。
- "moveLeft" 和 "moveRight":控制相机沿水平轴向左或向右移动。
- "mainView":将相机飞往预设的位置,并设置相机的方向和角度,最后在动画完成后再执行缩放操作。
3. Cesium相关操作:
- this.viewer.camera 是用来控制3D场景中相机行为的对象。
- moveUp, moveDown, moveLeft, 和 moveRight 方法用于即时地改变相机位置。
- flyTo 方法则用于创建一个平滑的相机飞行动画到指定的地理坐标,同时可以设定飞行结束后的回调函数。
4. 错误处理:
- 如果 data-action 的值不是预期的任何一种情况,代码将输出一条“未知动作”的日志信息。
3. choseIconInside
函数是一个用于处理用户交互的事件处理器,它根据被点击元素的 data-action
属性值执行特定的相机控制操作,从而实现对3D场景的导航和视角调整。这种设计模式使得代码更加模块化和可维护,同时也提高了用户界面的响应性和交互性。
4. 这里的switch
语句是一种选择结构,它允许程序基于不同的条件来执行不同的代码块。switch
语句通常用来替代多个if...else if...else
语句,当有大量条件需要检查时,使用switch
可以使代码更清晰、更简洁。
四. 事件委托的优势
减少事件监听器数量:通过在父元素上绑定事件监听器,避免了在每个子元素上分别绑定监听器,减少了内存消耗和提高了性能。
动态添加元素:如果页面中需要动态添加新的子元素,事件委托可以确保新元素也能自动获得事件处理能力,而无需重新绑定事件。
简化代码:使用事件委托可以使你的代码更加简洁和易于维护,尤其是当有大量相似类型的元素需要处理相同类型的事件时。
五. 注意事项
事件目标判断:在事件处理函数中,你需要确保检查
e.target
(事件的目标元素)是否是你想要处理的元素。这是因为事件冒泡也可能触发父元素上绑定的事件,即使点击的是父元素内部的其他非目标元素。事件阻止:有时你可能需要阻止事件的进一步传播,例如使用
e.stopPropagation()
。这样可以防止事件冒泡到更高级别的元素,避免触发不必要的事件处理。
e.stopPropagation()
是一个在JavaScript中用于阻止事件冒泡的方法。当你在DOM树中的某个元素上触发一个事件(比如点击事件),这个事件会首先在目标元素上触发,然后沿着DOM树向上冒泡,依次触发其祖先元素上的事件监听器。如果你不希望事件继续向上冒泡并触发更多的事件处理器,可以调用e.stopPropagation()
。调用
stopPropagation()
方法后,事件将不会继续在其祖先元素上调用任何事件处理器。这在处理复杂的DOM结构时非常有用,可以防止意外触发不需要的事件处理器,从而避免潜在的性能问题或逻辑错误。性能考量:虽然事件委托可以提高性能,但过多的事件监听器仍然可能影响性能。合理规划事件监听器的布局和层级可以进一步优化应用的响应速度。