DOM的事件系统是为了能让网页知道某些特定的事情发生了,以便针对特定事情进行特定处理。在这个事件系统当中,用户能对每个DOM元素的特定事件进行监听。

事件级别

DOM一共有四个级别,分别是DOM0、DOM1、DOM2和DOM3。由于DOM1没有事件的内容,所以对应的事件级别有三个,分别为DOM0事件处理、DOM2事件处理和DOM3事件处理

DOM0

ele.onclick = function(e) {}
这个级别的事件只能绑定在DOM元素的属性上面,而且一个DOM元素的同一类型事件只能绑定一个方法,方法的执行是在冒泡阶段执行

DOM2

ele.addEventListener(type, listener, options)
ele.addEventListener(type, listener, useCapture)
这个级别中的事件是通过调用DOM元素的 addEventListener 方法来实现,与DOM0级不同,同一类型事件能绑定多个方法,而且能决定方法在捕获阶段还是在冒泡阶段执行。方法的第三个参数能是一个对象或者是bool值:

  • 对象
    • capture:方法是否在捕获阶段执行
    • once:是否只调用一次,设定为true以后调用一次会自动移除listener
    • passive:是否禁用 preventDefault() ,设定为true后函数中的 e.preventDeault() 会无效化
  • 布尔值:方法是否在捕获阶段执行,默认为false

    DOM3

    DOM3在DOM2的基础上增加了一些事件类型,具体增加的列表可在这个链接查阅。
    此外DOM3提供了API让用户自定义事件,具体示例如下:
    创建事件构造函数: CustomEvent(type, eventInitDict) ,其中eventInitDIct的选项如下:

  • bubbles:一个布尔值,表明该事件是否会冒泡

  • cancelable:一个布尔值,表明该事件是否可以被取消
  • detail:当事件初始化时传递的数据,方法可以通过 e.detail 获取 ```javascript var obj = new EventTarget() // 添加一个适当的事件监听器 obj.addEventListener(“cat”, function(e) { process(e.detail) })

// 创建并分发事件 var event = new CustomEvent(“cat”, {“detail”:{“hazcheeseburger”:true}}) obj.dispatchEvent(event) ```

事件模型

DOM的数据结构是树,由此产生一个问题,一个元素触发事件时它的所有祖先元素都会触发事件,因此需要安排事件触发的先后顺序,W3C由此将事件的触发顺序分为三个阶段:

  1. 捕获阶段:window->document->html->body->。。。->目标节点,这阶段是从父元素到子元素由上而下传播
  2. 目标阶段:目标节点处理事件阶段
  3. 冒泡阶段:目标节点->。。。->body->html->document->window,这阶段跟捕获刚好相反,是由子元素到父元素由下向上传播

在捕获阶段中,我们无法阻止事件的传播,而在冒泡阶段,我们能通过 e.stopPropagation() 阻止事件向父元素传播。

事件委托

某些情况下我们需要对多个元素绑定同一个事件,为了减少绑定的事件数量,我们选择将事件绑定在它们的共同父元素上面,由父元素同一处理,这种技术称作事件委托,意思就是子元素将事件处理委托给父元素。
在具体事件过程中,第一步我们需要找到共同父元素,第二步就是父元素的事件处理根据 e.target 判断具体的子元素,针对不同的子元素进行处理。
这项技术有以下优点:

  • 节省需要绑定的事件数从而节省内存
  • 动态绑定:有时候我们需要插入DOM节点,一般还需要为DOM节点绑定对应的事件,有了事件委托,DOM节点事件可以委托给父元素,用户就能省去绑定事件的环节了

    Event对象常见API

  • event.stopPropagation():阻止冒泡

  • event.preventDefault():阻止默认行为
  • event.stopImmediatePropagation():阻止之后的绑定到同一元素的所有同类型listener调用
  • event.target:触发事件的元素
  • event.currrentTarget:处理当前事件的元素