浏览器事件知多少——JS事件流与事件处理程序

1,106 阅读3分钟

什么是JS的事件流?--事件机制

事件流描述的是从页面接收事件的顺序

一个事件的触发会涉及到哪些阶段

  1. 从window层往事件触发处传播,直到遇到注册的捕获事件会触发
//addEventListener用来给Dom节点注册一个点击事件
document.getElementById('root').addEventListener('click', function(){
  console.log(123)
})
  1. 传播到事件触发处时,触发注册事件
  2. 从事件触发处往window传播,遇到注册的冒泡事件会触发

这里疑惑就来了,好像听说浏览器的事件流是事件冒泡啊?怎么会变成先捕获后冒泡了呢?

addEventListener的第三个参数

addEventListener接收三个参数:

  • 要处理的事件名
  • 作为事件处理程序的函数
  • 一个布尔值

最后这个布尔值表示事件处理程序执行的阶段,默认为false,表示在冒泡阶段处理程序,若设为true则表示在捕获阶段执行。

<div id="parent" style="width:80px; height:80px; background:yellow">
    <div id="child" style="width:40px; height:40px; background:red"></div>
 </div>

 <script>
    var parent = document.getElementById('parent')
    var child = document.getElementById('child')
    parent.addEventListener('click', function(event){
      console.log('父盒子')
    }, true)
    child.addEventListener('click', function(event) {
      console.log('子盒子')
    }, false)
  </script>

以上代码若不设置第三个值,则默认冒泡阶段执行事件处理程序,打印顺序为子盒子->父盒子
若设为以上形式,则表示父盒子事件再捕获阶段就去执行,而子盒子仍再冒泡阶段执行,因此打印顺序为父盒子->子盒子

具体阶段如图所示:

阻止冒泡

child.addEventListener('click', function(event) {
    // 会阻止冒泡以及该容器之后所有的点击事件
    event.stopImmediatePropagation()
    // 只阻止冒泡
    event.stopPropagation() 
    console.log('子盒子')
}, false)

事件处理程序(事件侦听器)

事件处理程序表示响应某个事件的函数(以on开头)
目前主要支持的有三种:

  1. DOM0级事件处理程序
  2. DOM2级事件处理程序
  3. IE级事件处理程序

DOM0级事件处理程序

DOM0级的事件处理程序是在绑定事件的元素的作用域中运行

var btn = document.getElementById('myBtn')
btn.onclick = function () {
  console.log(this.id) // myBtn
}
// 删除DOM0级方法指定的事件处理程序
btn.onclick = null

这种形式书写较为直观,简洁,但缺点 只支持一个事件处理程序

DMO2级事件处理程序

定义了两个方法

  1. addEventListener()

  2. removeEventListener()

所有的DOM节点都包含这两个方法,接收三个参数:要处理的时间名、作为事件处理程序的函数、事件流形式

作用域:其依附元素的作用域种运行
优点:可以添加多个事件处理程序,并顺序执行

IE事件处理程序

定义了两个方法

  1. attachEvent()
  2. detachEvent()

接收两个相同的参数:事件处理名称和事件处理程序函数

作用域:事件处理程序会在全局作用域中运行

var btn = document.getElementById('myBtn')
btn.attachEvent("onclick", function(){
  console.log(this === window) // true
})

区别:可以为一个元素添加多个事件处理程序,倒序执行

三种事件处理程序对比

对比 DOM0级 DOM2级 IE级
形式 element.onclick element.addEventListener('onclck',callback,false) element.attachEvent('onclick',callback)
执行阶段 冒泡阶段 冒泡(默认)/捕获阶段 冒泡阶段
作用域 其依附元素的作用域 其依附元素的作用域 事件处理程序会在全局作用域中运行
多个事件处理程序 不支持(唯一) 支持,且顺序执行 支持,倒序执行