DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)

1. 事件绑定方式

1. 直接给元素添加事件属性
<input  onclick="alert('我被点击了!')"  type="button"  value="点我试试" />

优点:大家都会,几乎所有的浏览器都支持

缺点:夹杂在HTML代码中,代码不简洁;这种事件写法效率不高;不符合“行为,样式,结构”相分离。

2. js中赋值事件
<button id="btn">点我button>
<script>
  var btn = document.getElementById("btn");
  btn.onclick = function() {
    console.log("事件触发")
  }
  
// 事件解绑
btn.onclick = null
script>

优点:符合“行为,样式,结构”相分离;便于操作当事对象;方便读取事件对象

缺点: 只能给一个元素注册一个相同事件,绑定多个相同事件,后一个会覆盖前一个

  var btn = document.getElementById("btn");
  btn.onclick = function() {
    console.log("事件触发1")
  }
  btn.onclick = function() {
    console.log("事件触发2")
  }
// 事件触发1
3. 事件监听 addEventListener()
<button id="btn">点我button>
<script>
  var btn = document.getElementById("btn");
  btn.addEventListener("click", function () { 
    console.log("事件触发");
  });
 
// 事件解绑
btn.removeEventListener("click", function () { 
    console.log("事件解绑触发");
})
script>

addEventListener第三个参数,Boolean类型值,可指定事件冒泡阶段还是捕获阶段触发,true-捕获,false-冒泡,默认false,既冒泡。

优点:可以注册多个相同时间,后面的事件不会被覆盖

<button id="btn">点我button>
<script>
  var btn = document.getElementById("btn");
  btn.addEventListener("click", function () { 
    console.log("事件触发1");
  });
  btn.addEventListener("click", function () { 
    console.log("事件触发2");
  });
script>
// 事件触发1
// 事件触发2

缺点: 写法相对复杂

2. DOM事件流

DOM事件流(event flow )存在三个阶段:
  1. 事件捕获阶段
  2. 处于目标阶段
  3. 事件冒泡阶段。
    DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)_第1张图片
事件捕获(由外到内):

通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。

事件冒泡(有内到外):

与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。

dom标准事件流的触发的先后顺序为:先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。不同的浏览器对此有着不同的实现,IE10及以下不支持捕获型事件,所以就少了一个事件捕获阶段,IE11、Chrome 、Firefox、Safari等浏览器则同时存在。

实践:
<body>
<div id="box1">
    <span>box1span>
    <div id="box2">
        <span>box2span>
        <div id="box3"><span>box3span>div>
    div>
div>

<script>
    var box1 = document.getElementById("box1");
    var box2 = document.getElementById("box2");
    var box3 = document.getElementById("box3");
    //给每个元素添加点击事件

    box1.onclick = function () {
        console.log("事件冒泡——box1");
    };

    box2.onclick = function () {
        console.log("事件冒泡——box2");
    };

    box3.onclick = function () {
        console.log("事件冒泡——box3");
    };

    box1.addEventListener("click", function () {
        console.log("事件捕获——box1");
    }, true);

    box2.addEventListener("click", function () {
        console.log("事件捕获——box2");
    }, true);

    box3.addEventListener("click", function () {
        console.log("事件捕获——box3");
    }, true);

script>
body>

当点击 box3 的后,会先由外到内开始进行捕获阶段,然后有内到外开始冒泡阶段
DOM 事件相关知识总结——事件绑定、事件流(事件冒泡、捕获)_第2张图片

取消事件捕获、事件冒泡
 	var box1 = document.getElementById("box1");
    var box2 = document.getElementById("box2");
    var box3 = document.getElementById("box3");
    //给每个元素添加点击事件

    box1.onclick = function () {
    	e.stopPropagation();
        console.log("事件冒泡——box1");
    };

    box2.onclick = function () {
    	e.stopPropagation();
        console.log("事件冒泡——box2");
    };

    box3.onclick = function () {
    	e.stopPropagation();
        console.log("事件冒泡——box3");
    };

    box1.addEventListener("click", function () {
    	e.stopPropagation();
        console.log("事件捕获——box1");
    }, true);

    box2.addEventListener("click", function () {
    	e.stopPropagation();
        console.log("事件捕获——box2");
    }, true);

    box3.addEventListener("click", function () {
    	e.stopPropagation();
        console.log("事件捕获——box3");
    }, true);
stopPropagation与stopImmediatePropagation区别:
1. stopPropagation:

阻止事件像外冒泡

<div id="root">
   <div id="box">div>
div>
<script>
  var root = document.getElementById("root");
  var box = document.getElementById("box");
  box.addEventListener("click", function (event) { 
    event.stopPropagation();
    console.log("box-事件触发1");
  });
  box.addEventListener("click", function () { 
    console.log("box-事件触发2");
  });
  root.addEventListener("click", function () { 
    console.log("root-事件触发");
  });
script>
// box-事件触发1
// box-事件触发2
2. stopImmediatePropagation:

阻止后面相同元素事件触发

<div id="root">
   <div id="box">div>
div>
<script>
  var root = document.getElementById("root");
  var box = document.getElementById("box");
  box.addEventListener("click", function (event) { 
    event.stopImmediatePropagation();
    console.log("box-事件触发1");
  });
  box.addEventListener("click", function () { 
    console.log("box-事件触发2");
  });
  root.addEventListener("click", function () { 
    console.log("root-事件触发");
  });
script>
// box-事件触发1
// root-事件触发
事件冒泡的作用——事件委托
<body>
<div id="box">
    <p class="hehe">我是文本内容p>
    <p class="hehe">我是文本内容p>
    <p>我是文本内容p>
    <span>我是span的内容span>
div>


<script>
    //事件委托
    //我们需要根据冒泡的元素不同,进行筛选,只有p标签才能够执行事件
    //第一步添加box的事件
    box.onclick = function (e) {
        e.stopPropagation()
        //需要获取,当前这个事件是由哪一个子元素触发的
        //第二步 兼容事件对象e
        var e = e || window.event;

        //第三步 兼容取出触发事件的元素的方式  target srcElement
        var tar = e.target || e.srcElement;

        //第四步 检测tar是什么标签
//        if (tar.nodeName.toLowerCase() == "p") {
        if (tar.nodeName.toUpperCase() == "P") {
            console.log("呵呵,我是p的代码");
        }
    };

    //可以通过nodeName属性获取到元素的标签名
    console.log(box.nodeName);
script>
body>

你可能感兴趣的:(javascript,html,前端)