DOM事件深入浅出

352 阅读4分钟

一、DOM分级与DOM事件模型的关系

在W3C DOM标准中先后有三个版本:

  • DOM1级、DOM2级、DOM3级

在DOM标准正式形成之前就有些被广泛应用的规则,也就是我们之前常提及的DOM0级

DOM事件模型(指绑定事件的方式,以及事件传播方式)有三个:

  • DOM0级中定义的DOM0级模型、DOM2级定义的DOM2级模型、IE事件模型

DOM0级中有"原始事件模型",DOM2级中除了定义了一些DOM相关的操作之外,还定义了一个事件模型。DOM1级没有定义事件相关的内容,仅仅是定义了HTML和XML文档的底层结构。DOM3级也仅仅定义了一些DOM相关的操作,所有这两个版本的DOM标准并不存在事件模型。

二、DOM分级

DOM0级

包含了一些基本事件和原始事件模型,该模型指明;1应该如何为元素添加事件监听,在该模型里事件不会传播,所有也没有事件流。同时,用事件的返回值来表示是否阻断浏览器的默认行为。

为元素绑定事件监听的方式有两种:

  1. 在标签上直接为事件绑定对应的回调(内联事件),但是这种方法是没法使用闭包和匿名函数的
<input type='button' onClick='func()'>
  1. 通过JS指定事件的回调函数,这种方式等价于内联事件
var btn=document.getElementById('.btn')
btn.onClick=func

监听回调的返回值为false时,可以阻止浏览器默认行为。 移除事件的方式只有一种

btn.onClick=null

这种方式所有浏览器都兼容,但是逻辑和显示没有分离。

在DOM0级事件模型中,回调函数被直接赋值到对应的监听函数中。就好像我们用let name='zhangsan',定义了一个变量通过name='lisi'改变name='lisi'的值,前面一个被赋予的值自然就被顶替掉了。所以这种直接赋值的方法是很难实现为事件添加多个回调函数的。同时,赋值的方式可以保证回调函数中的this指向的是绑定事件监听的元素。

DOM1级

没有定义出新的事件模型,仅仅是定义了HTML和XML文档的底层结构。

DOM2级

在DOM2级中,添加了很多新的事件。该模型指定了新的添加、移除事件监听的方式,还添加了事件流。DOM2级把新增的事件分成五种类型

  • UI事件:DOMActive、DOMFocusIn、DOMFocousOut
  • 鼠标事件:mousedown、mouseup、click、dbclick
  • 键盘事件:keydown、keypress、keyup
  • HTML事件:load、upload、abort、error、select、change、submit、reset、resize、scroll、focus、blur
  • 变动事件:底层DOM结构发生改变时触发
    • DOMSubtreeModified:DOM 结构中发生任何变化时都会触发。这个事件在其他任何事件触发后都会触发。
    • DOMNodeInserted:一个节点作为子节点,被插入到另一个节点上时触发
    • DOMNodeRemoved:节点从其父节点中被移除时触发
    • DOMNodeInsertIntoDocument:在一个节点被直接插入文档或通过子树间接插入文档之后触发。这个事件在 DOMNodeInserted 之后触发
    • DOMNodeRemovedFromDocument:在一个节点被直接从文档中移除或通过子树间接从文档中移除之前触发。这个事件在 DOMNodeRemoved 之后触发 
    • DOMAttrModified:在特性被修改之后触发
    • DOMCharacterDataModified:在文本节点的值发生变化时触发。 在DOM2级事件模型中,借助发布订阅模式操作事件回调可以让一个事件添加多个回调监听。同时还要精准的移除某一个具体的监听回调。
var btn = document.getElementById('.btn');
btn.addEventListener(‘click’, showMessage1, false); // 为btn绑定监听事件,并添加一个回调函数
btn.addEventListener(‘click’, showMessage2, false); // 为btn的点击事件再添加一个监听回调
btn.removeEventListener(‘click’, showMessage1, false); // 清除btn上的第一个监听回调

其次,DOM2级事件模型把事件传播分成了三个阶段:

  • 捕获阶段:事件由最外层像内层传播,一直传递到对应的触发事件元素
  • 命中阶段:执行对于的回调
  • 冒泡阶段:从命中元素向外层传播,一直传递到最外层

DOM3级

再次增加了一些事件,提升了交互能力。

三、IE事件模型

在该模型里,事件的传播没有捕获阶段,只有命中和冒泡阶段。 在IE9及之前的版本,为元素绑定事件监听和移除监听通过下面的方式

btn.attachEvent('onclick',showMe)

btn.detachEvent('onclick',showMe)

在IE中,event不能直接获取,需要通过window.event的方式。
阻止浏览器默认行为要通过stopPropagatiion(return false)实现
在之后的版本就和DOM2事件模型中保持一致了。

我们还需要注意到,在DOM模型中事件类型是没有on的,而IE事件模型中,事件类型是需要加上on的。