一、事件流
事件流指的是事件完整执行过程中的流动路径,分为捕获阶段、冒泡阶段。如上图
二、事件捕获
当一个元素的事件被触发时,会从DOM的根元素开始,依次调用同名事件(从外到里,从父到子)。
DOM.addEventListener(事件类型, 事件处理函数, 是否使用捕获)
true:代表捕获触发;
false/不传:代表冒泡触发
三、事件冒泡
当一个元素的时间被触发时,回一次向上调用所有父级元素的同名事件(从里到外,从子到父) 。
阻止冒泡:事件对象.stopPropagation()
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const father = document.querySelector('.father');
const son = document.querySelector('.son');
father.addEventListener('click',function() {
console.log('father')
})
son.addEventListener('click',function() {
console.log('son')
})
</script>
</body>
<body>
<div class="father">
<div class="son"></div>
</div>
<script>
const father = document.querySelector('.father');
const son = document.querySelector('.son');
father.addEventListener('click',function() {
console.log('father')
})
son.addEventListener('click',function(e) {
console.log('son')
e.stopPropagation();
})
</script>
</body>
四、事件委托
事件委托也叫事件委派、事件代理。就是将原本需要注册在子元素的事件委托给父元素,让父元素担当时间监听的职务。
原理是利用时间冒泡的特点,给父元素注册事件,在触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
可以减少注册次数,提高程序性能。
利用事件委托方式,需要找到真正触发的元素:事件对象.target.tagName
// 不使用事件委托
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
const lis = document.querySelectorAll('ul li')
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('click',function() {
console.log('我被点击了')
})
}
</script>
</body>
// 使用了事件委托
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
<script>
const ul = document.querySelector('ul')
ul.addEventListener('click',function(){
console.log('我下面的li被点击了')
})
</script>
</body>