DOM 事件模型/机制和事件委托

571 阅读3分钟

1,DOM级别

有DOM0~4级,其中dom1级没有定义相关事件就不是标准的dom事件,它似乎是专注于 HTML 和 XML 文档模型

  • DOM0级(HTML事件):element.onclick=function(event){}
  <button type="button" onclick="hi()"></button>
  function hi() {
      console.log('Hi World');
  }
  1. 缺点一:一个元素同种类型的事件只能注册一个事件处理程序,多事件会被互相覆盖
  2. 却大的缺点:HTML和JS耦合太强,如果我们需要修改函数名 就必须修改两个地方
  3. 优点:是不需要操作DOM来完成事件绑定
  • DOM2级:element.addEventListener('click',function(event){},false)冒泡
    <button id="btn" type="button"></button>
    var btn = document.getElementById('btn');    
    function hi() {
        console.log('hi World');
    }    
    btn.addEventListener('click', hi, false);  //没有on
    btn.addEventlistener('mouseover',showfn,false) //允许添加多个事件
    // btn.removeEventListener('click', hi, false); 解绑事件
  1. 同一个元素上的同类型事件可以注册多个处理函数。事件触发时按照注册顺序触发。
  2. 支持捕获和冒泡,当布尔值为ture是捕获,falsy为冒泡()、
  3. 注意,IE事件处理程序没有第三个参数,因为IE早期版本只支持事件冒泡,所以默认就是事件冒泡。
  • DOM3级:element.addEventListener('keyup',function(event){},false),新增的鼠标键盘事件

可以自定义事件 在DOM2级的事件上添加了很多事件类型 UI事件 load,scroll 焦点事件, blur,focus 鼠标事件,dbclick,mouseup ...

2,DOM事件模型和事件流

DOM事件模型分别为捕获和冒泡。一个事件发生后,会在子元素和父元素之间传播。这种传播分成三个阶段。

DOM事件模型示意图

1,捕获阶段

事件从window对象自上而下向目标节点传播的阶段 
addEventListener的第三个参数bool为ture 
不可取消,但冒泡可以阻止

2,目标阶段(target):真正的目标节点正在处理事件的阶段

3,冒泡阶段:事件从目标节点自下而上向window对象传播的阶段。

e.stopPropagation()中断冒泡,浏览器不再向上传播// 一般用于封装某些独立的组件
一些不能取消的冒泡事件:Bubbles表示是否冒泡;Cancelable表示是否支持开发者取消冒泡 具体口查看mdn文档,英文版更全
<div class="outter" hiOutter()>
  <div class="middle" hiMiddle()>
    <div class="inner" hiInner()>
      我目标就在此
    </div>
  </div>
</div>

function hiOutter() {
    console.log('hiOutter');
}
function hiMiddle() {
    console.log('hiMiddle');
} 
function hiInner() {
    console.log('hiInne');
} 

事件委托

  1. 定义

事件委托指的是不在事件的发生地(直接DOM)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到被触发的子元素事件,通过判断事件发生元素DOM的类型,来作出不同的响应。当子元素有很多时,使用事件委托可以避免对特定的每个节点添加事件监听器,事件监听被添加到它们的父元素上,事件监听函数这是可以从子元素上冒泡上来的事件,找到是哪个子元素事件。

  1. 事件委托举例

最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。

第一步:给父元素绑定事件。给元素ul添加绑定事件,通过addEventListener为点击事件click添加绑定。

第二步:监听子元素的冒泡事件。这里默认是冒泡,点击子元素li会向上冒泡。

第三步:找到是哪个子元素的事件。 通过匿名回调函数的参数event用来接收事件对象,通过event.target获取触发事件的目标。

  1. 使用事件委托的好处
  • 省内存
  • 动态绑定