一、事件流
事件流指的是事件完整执行过程中的流动路径,分为捕获阶段、冒泡阶段。如上图
二、事件捕获
当一个元素的事件被触发时,会从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>