> 文章列表 > js的dom事件流、事件委托和阻止绑定事件触发

js的dom事件流、事件委托和阻止绑定事件触发

js的dom事件流、事件委托和阻止绑定事件触发

主要讲解事件绑定和事件委托,onclick事件和addEventListener的区别

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.father {width: 100%;height: 300px;display: flex;}.child {width: 100px;height: 100px;background-color: aquamarine;margin: 10px;}</style>
</head>
<body><div class="father"><div class="child">1</div><div class="child">2</div><div class="child">3</div><div class="child">4</div><div class="child">5</div></div>
</body>
</html>

示例1:给元素绑定click点击事件

使用onclick

  • 重复绑定点击事件,后面的事件会覆盖前面的事件
<script>const element = document.querySelector('.father')element.onclick = () => {console.log('点击事件1')}element.onclick = () => {console.log('点击事件2')}// 控制台只会输出:点击事件2
</script>

使用addEventListener

  • 重复绑定点击事件,事件不会被覆盖(类似于发布订阅模式,on中收集的事件存放在数组中,在emit时会遍历执行事件)
  <script>const element = document.querySelector('.father')element.addEventListener('click', () => {console.log('点击事件1')})element.addEventListener('click', () => {console.log('点击事件2')})// 控制台输出 点击事件1 点击事件2</script>

语法:document.addEventListener(event, function, useCapture)
useCapture是可选的布尔值,指定事件是否在捕获或冒泡阶段执行

  • true:事件在捕获阶段执行
  • false:默认值,事件在冒泡阶段执行
element .addEventListener('click', (el) => {console.log(el.currentTarget) // 当前绑定事件的元素console.log(el.target) // 点击事件触发的元素
})

示例2:默认给每个child元素绑定一个点击事件,现在如果class名包含out-box的元素需要阻止之前绑定的点击事件

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.father {width: 100%;display: flex;}.child {width: 100px;height: 100px;background-color: aquamarine;margin: 10px;}</style>
</head>
<body><div class="father"><div class="child">1<div class="bady-one">1-1<div class="yang-two">1-1-1</div></div></div><div class="child">2<div class="bady-one out-box">2-1<div class="yang-two">2-1-1</div></div></div><div class="child">3<div class="bady-one">3-1<div class="yang-two">3-1-1</div></div></div></div><script>// 示例:默认给每个child元素绑定一个点击事件,现在如果class名包含out-box的元素需要阻止之前绑定的点击事件const childElements = document.querySelectorAll('.child')childElements.forEach(el => {el.addEventListener('click', () => {console.log('child点击事件')})}) // 默认第三个参数为false,在冒泡阶段执行</script><script>// 处理需求:在捕获阶段找到class名包含out-box的元素,并阻止冒泡const fatherElement = document.querySelector('.father')fatherElement.addEventListener('click', (el) => {const curentElement = el.target // 点击事件触发的元素,如果不是child元素,需要再找到它的class为child的父元素const parentElement = getParentElement(curentElement, 'child')if (curentElement.classList.toString().indexOf('child') !== -1 || parentElement) {if (curentElement?.querySelector('.out-box') || parentElement?.querySelector('.out-box')) {// console.log('点击事件')el.preventDefault() // 阻止默认行为el.stopPropagation() // 阻止冒泡}}}, true) // true点击事件在捕获阶段执行// 获取一个元素指定的父元素,使用元素的parentElement属性和while循环向上遍历DOM树,直到找到指定的父元素为止function getParentElement(target, className) {let parent = target.parentElementwhile (parent) {if (parent.classList.toString().indexOf(className) !== -1) {return parent}parent = parent.parentElement}return null}</script>
</body>
</html>

DOM事件流
js的dom事件流、事件委托和阻止绑定事件触发
事件触发经典案例
js的dom事件流、事件委托和阻止绑定事件触发

解析:前面提到的DOM事件流的执行顺序是先捕获再冒泡,所以dom事件流从外向内捕获过程就是grandma -> monther -> daughter -> baby,而只有monther和daughter设置了useCapture = true,所以在捕获阶段就先将事件处理了,而grandma和baby并未设置useCapture = true,默认是false,而我们又是点击的baby所以首先会先处理baby目标事件,然后再通过冒泡到grandma事件。