Contents

DOM事件

事件流

事件两种模型:捕获和冒泡

/images/v2-bf3b8dbab027713a2b21b9e8a5b7a6c4_720w.jpg

javascript复制代码// 鼠标点击子元素后,打印顺序为
// 父捕获
// 子捕获
// 子冒泡
// 父冒泡

<html>
  <div class="parent">
    <div class="child">子元素</div>
  </div>
  <script>
     let parentDom = document.querySelector('.parent');
     parentDom.addEventListener('click', function () {console.log('父捕获'); }, true)
     parentDom.addEventListener('click', function () {console.log('父冒泡');}, false)

     let childDom = document.querySelector('.child')
     childDom.addEventListener('click', function () {console.log('子捕获');}, true)
     childDom.addEventListener('click', function () {console.log('子冒泡');}, false)
  </script>
</html>

流程:

  1. 捕获
  2. 目标阶段
  3. 冒泡

事件捕获流程

从上到下

window -> document -> html -> body->元素

Event 对象

event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
event.target
event.currentTarget
函数 作用
event.stopImmediatePropagation() 能阻止父类元素冒泡,也会阻止当前节点的其他事件处理。
event.stopPropagation() 阻止父类元素的冒泡,不影响当前节点的其他事件处理。
event.targe 事件的真正发出者
event.currentTarget 监听事件者

节点绑定多个事件,先绑定的事件会处理。

例子:

<div id="div">
    <input type="text" id="input"/>
</div>
var dom = document.querySelector('#input');
dom.addEventListener('keyup', function (e) {
    console.log('keyup 1');
})
dom.addEventListener('keyup', function (e) {
    console.log('keyup 2');
})

dom.addEventListener('click', function (e) {
    //e.stopPropagation();
    e.stopImmediatePropagation();
    console.log('dom click 1');
})
dom.addEventListener('click', function (e) {
    console.log('dom click 2');
})

var div = document.querySelector('#div');
div.addEventListener('click', function (e) {
    console.log('div click 1');
})
div.addEventListener('click', function (e) {
    console.log('div click 2');
})

结果说明:

  • 调用stopPropagation方法后,dom click 1dom click2执行。阻止冒泡,父类元素的事同类事件不会执行。blurkeyup事件触发后会依次执行。
  • 调用stopImmediatePropagation方法后,点击输入框,只会执行dom click1。阻止冒泡,父类元素的事同类事件不会执行。blurkeyup事件触发后会依次执行。

事件委托(代理)

利用冒泡的原理,将元素的事件委托给它的父级或者更外级的元素处理。

优点

  1. 同类元素的事件委托给上级元素,不需要给每个元素都绑定事件,减少内存占用,提升性能
  2. 动态新增元素无需重新绑定事件。

缺点

  1. 利用事件冒泡的原理,不支持不冒泡的事件;
  2. 层级过多,冒泡过程中,可能会被某层阻止掉;
  3. 把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

注意点

  1. 事件委托的实现依靠的冒泡,因此不支持事件冒泡的事件就不适合使用事件委托。