# DOM事件机制

  • 基本概念: DOM事件的级别
  • DOM事件模型 捕获 冒泡
  • DOM事件流
  • 描述DOM事件捕获的具体流程
  • Event对象的常见应用
  • 自定义事件

# 事件级别

// DOM0 
element.onclick= function(){}
// DOM2 
element.addEventListener('click', function(){}, false)
// DOM3 
element.addEventListener('keyup',functoin(){}, false)
1
2
3
4
5
6

# 事件模型

  • 捕获
  • 冒泡
  • 事件流 一个完整的事件流分为三个阶段,
    • 第一阶段是捕获
    • 第二阶段事件通过捕获到达目标元素这就是目标阶段,
    • 第三个阶段就是从目标元素上传到window对象,这就是冒泡的过程

事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。

事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

# 描述dom事件捕获的具体流程

​ window> document> html> body> 父元素>子元素

  <div id="ev">
    <style>
    #ev {
      width: 300px;
      height: 100px;
      background: red;
      color: #fff;
      text-align: center;
      line-height: 100px;
    }
    </style>
    目标元素
  </div>
1
2
3
4
5
6
7
8
9
10
11
12
13

var ev = document.getElementById('ev')
  window.addEventListener('click', function(){
    console.log('window captrue')
  }, true); // true 捕获 false 、、 冒泡

  document.addEventListener('click', function(){
    console.log('document captrue')
  },true)

  document.documentElement.addEventListener('click', function(){
    console.log('html captrue')
  }, true)

  document.body.addEventListener('click', function(){
    console.log('body captrue')
  },true)

  ev.addEventListener('click', function(){
    console.log('ev captrue')
  }, true)

  //自定义事件
  var eve = new Event('test');
  ev.addEventListener('test', function(){
    console.log('test  dispatch')
  })
  setTimeout(() => {
    ev.dispatchEvent(eve)
  }, 1000);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

和事件冒泡相反,事件捕获是自上而下执行,我们只需要将addEventListener的第三个参数改为true就行。

# event对象的常见应用

event.prentDafault() // 阻止默认事件
event.stopPropagation() // 阻止冒泡
event.stopImmediatePropagation() 
// 阻止事件冒泡并且阻止相同事件的其他侦听器被调用
// 如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,
// 它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,
// 则当前元素剩下的监听函数将不会被执行。
 event.currentTarget
// 当前被绑定的事件

// 指的是绑定了事件监听的元素(可以理解为触发事件元素的父级元素)

// w3c
// currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
//在捕获和起泡阶段,该属性是非常有用的,因为在这两个节点,它不同于 target 属性。
  event.target
// 指的是真正触发事件的那个元素
// w3c 
// target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  • 面试中会隐含问你current和target的区别 事件委托, 如:一个for循环给dom注册了n多事件,你怎么优化? 用事件代理,将子元素的事件绑定到父元素上,做响应的时候,判断当前的是哪个子元素被点击,使用target来判断 target值当前被点击的元素 currentTarget 当前被绑定的事件, 例子中指的是被绑定事件的父级元素
var eve = new Event('custome');
ev.addEventListener('custome', function(){
	console.log('custome')
})
ev.dispatchEvent(eve);
1
2
3
4
5

# 自定义事件

  var eve = new Event('test');
  ev.addEventListener('test', function(){
    console.log('test  dispatch')
  })
  setTimeout(() => {
    ev.dispatchEvent(eve)
  }, 1000);
1
2
3
4
5
6
7

一秒钟后打印

CustomEvent