事件有DOM0,DOM2,DOM3的区分

DOM0

就是直接通过onclick写在html里面的事件,比如

<input onclick = "alert(1)">

DOM0的事件具有极好的跨浏览器优势, 会以最快的速度绑定, 如果你通过DOM2绑定要等到JS运行, DOM0不用, 因为DOM0是写在元素上面的哇;

DOM2

是通过addEventListener绑定的事件,还有IE下的DOM2事件通过attacheEvent绑定;事件规定了事件流包含三个阶段包括: 1:事件捕获, 2:处于目标阶段, 3:事件冒泡阶段

事件流

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .out{
            width: 200px;
            height:200px;
            border: 1px solid red;
        }

        .middle{
            width:150px;
            height:150px;
            border: 1px solid rebeccapurple;
        }
        .inner{
            width:100px;
            height:100px;
            border: 1px solid blue;
        }
    </style>
</head>
<body>

<div class="out">
    out
    <div class="middle">
        middle
        <div class="inner">
            inner
        </div>
    </div>
</div>
<script>
    document.querySelector('.out').addEventListener('click', function (e) {
        console.log("out,捕获")
    },true);
    document.querySelector('.out').addEventListener('click', function (e) {
        console.log("out,冒泡")
    },false);
    document.querySelector('.middle').addEventListener('click', function () {
        console.log("middle,捕获")
    },true);
    document.querySelector('.middle').addEventListener('click', function () {
        console.log("middle,冒泡")
    },false);
    document.querySelector('.inner').addEventListener('click', function () {
        console.log("inner,捕获")
    },true);
    document.querySelector('.inner').addEventListener('click', function () {
        console.log("inner,冒泡")
    },false);
    document.querySelector('.out').addEventListener('click', function (e) {
        console.log("out2,捕获2")
    },true);
    document.querySelector('.out').addEventListener('click', function (e) {
        console.log("out2,冒泡2")
    },false);
</script>
</body>
</html>

输出

1.如果多个均为 true,则外层的触发先于内层;如果多个均为 false,则内层的触发先于外层。

  1. true 在捕获阶段触发,false在冒泡阶段触发,true 的触发顺序总是在 false 之前;
  2. 都是true的情况下,是由外到内,都是false的情况下由内向外
  3. 先输出捕获,再输出冒泡
  4. 同一元素的绑定两次(true/false)捕获和冒泡,只是跟绑定顺序有关系
  5. 捕获阶段删除 子元素,绑定的事件还是会执行完成.
  6. chrome开发者工具内 getEventListeners(ele)可以获取绑定事件列表
 obj.addEventListener("click", function(){console.log(s1)}, true); // 捕获方式
 obj.addEventListener("click", function(){console.log(s2)}, false); // 冒泡方式

输出 s1->s2

DOM事件流

DOM2级事件规定的时间流包括 三个阶段:

 事件捕获阶段
 处于目标阶段
 事件冒泡阶段

注意:在DOM事件流中,实际的目标在捕获阶段不会接收到事件,下一个阶段是处于目标阶段,这时事件被触发,最后进入事件冒泡阶段。我们认为处于目标阶段是事件冒泡阶段的一部分。

DOM3

是一些新的事件,区别DOM3和DOM2的方法,我感觉是DOM3的事件有区分大小写,DOM2没有

事件对象event下的属性和方法:

因为各个浏览器的事件对象不一样, 把主要的时间对象的属性和方法列出来;
bubble :    表明事件是否冒泡
cancelable :  表明是否可以取消冒泡
currentTarget : 当前时间程序正在处理的元素, 和this一样的;
defaultPrevented: false ,如果调用了preventDefualt这个就为真了;
detail: 与事件有关的信息(滚动事件等等)
eventPhase: 如果值为1表示处于捕获阶段, 值为2表示处于目标阶段,值为三表示在冒泡阶段
target || srcElement: 事件的目标
trusted: 为ture是浏览器生成的,为false是开发人员创建的(DOM3)
type : 事件的类型
view : 与元素关联的window, 我们可能跨iframe;
preventDefault()    取消默认事件;
stopPropagation() 取消冒泡或者捕获;
stopImmediatePropagation() (DOM3)阻止任何事件的运行;
//stopImmediatePropagation阻止 绑定在事件触发元素的 其他同类事件的callback的运行

IE下的事件对象是在window下的,而标准应该作为一个参数, 传为函数第一个参数;
IE的事件对象定义的属性跟标准的不同,如:
cancelBubble 默认为false, 如果为true就是取消事件冒泡;
returnValue 默认是true,如果为false就取消默认事件;
srcElement, 这个指的是target, Firefox下的也是srcElement;

阻止冒泡/阻止捕获

(说明:尽管这里我使用了DOM2级事件处理程序,并设置每个事件为冒泡阶段发生,但是即使使用DOM0级,得到的结果也是这样的,冒泡是默认的)

  1. 冒泡的 button->body->html->window
  2. 事件捕获 window->html->body->button
  3. stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕获,也可以阻止处于目标阶段。
  4. stopImmediatePropagation

但是我们可以使用DOM3级新增事件stopImmediatePropagation()方法来阻止事件捕获,另外此方法还可以阻止事件冒泡。应用如下:

document.getElementById("second").addEventListener("click",function(){
    alert("second");
    event.stopImmediatePropagation();
},true);
  1. stopImmediatePropagation() 和 stopPropagation()的区别 后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生 demo

参考 JavaScript事件机制 javascript事件机制底层实现原理 addEventListener 和 onclick 有什么不同?