DOM事件与事件委托

173 阅读3分钟

请简述 DOM 事件模型或 DOM 事件机制

DOM事件流是先捕获再冒泡,事件触发则两者都可。

  • DOM事件模型
  1. 冒泡型事件(Bubbling)先在最精确的元素上触发,然后向上传播,直到根节点。反映到DOM树上就是事件从叶子节点传播到根节点。

  2. 捕获型事件(Captrue)先在最顶级的元素上触发,传播到最低级的元素上。在DOM树上的表现就是由根节点传播到叶子节点。

从外向内找监听函数,叫事件捕获

从内向外找监听函数,叫事件冒泡

  • 事件绑定 API:addEventListener
target.addEventListener(type, listener, useCapture);
  • type 事件类型。
  • listener 事件触发实际执行的匿名函数。
  • userCapture 可选,类型为 Boolean,意思是是否执行事件捕获阶段。加上true则让 fn 走捕获,即当浏览器在捕获阶段发现有 fn 监听函数,就会调用 fn ,并提供事件信息。

image.png

题目

有如下的 HTML 文档结构:

<div id="parent">
    <child id="child" class="child">
        点我
    </child>
</div>

第一次执行如下 JavaScript 代码:

document.getElementById("parent").addEventListener("click", function () {
    alert(`parent 事件触发,` + this.id);
});

document.getElementById("child").addEventListener("click", function () {
    alert(`child 事件触发,` + this.id);
});

第二次执行另一套 JavaScript 代码:

document.getElementById("parent").addEventListener("click", function (e) {
    alert(`parent 事件触发,` + e.target.id);
});

document.getElementById("child").addEventListener("click", function (e) {
    alert(`child 事件触发,` + e.target.id);
});

第三次再执行一套:

document.getElementById("parent").addEventListener("click", function (e) {
    alert(`parent 事件触发,` + e.target.id);
}, true);

document.getElementById("child").addEventListener("click", function (e) {
    alert(`child 事件触发,` + e.target.id);
}, true);

问题如下:

点击 id 为 child 的 div 后,这三份 JavaScript 代码的执行结果分别是什么?

答案:

  • 第一次结果为:先弹出“child 事件触发,child”,再弹出“parent 事件触发,parent”。
  • 第二次结果为:先弹出“child 事件触发,child”,再弹出“parent 事件触发,child”。
  • 第三次结果为:先弹出“parent 事件触发,child”,再弹出“child 事件触发,child”。

关于 listener 中的 this 和 target

targetcurrentTargetcurrentTargetthis很像)

  1. 区别
  • e.target - 用户操作的元素(点击了哪个就返回哪个)
  • e.currentTarget - 程序员监听的元素(哪个元素绑定了就返回哪个)
  • this 是 e.currentTarget,不推荐使用它(哪个元素绑定了就返回哪个)
  1. 举例
  • div > span{文字},用户点击文字
  • e.target 就是 span
  • e.currentTarget 就是 div,span没有点击事件

事件对象阻止默认行为

让链接不跳转 或者让提交按钮不提交

e.preventDefault()常用

        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
                e.preventDefault(); //  dom 标准写法
            })
            // 传统的注册方式
        a.onclick = function(e) {
            // 普通浏览器 e.preventDefault();  方法
            // e.preventDefault();
            // 低版本浏览器 ie678  returnValue  属性
            // e.returnValue;
            // 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
            return false;
            alert(11);

阻止冒泡

有时候不需要传播到DOM最顶层节点,则可以阻止冒泡

  • 利用事件对象里面的e.stopPropagation()方法
  • IE678利用事件对象e.cancelBubble=true

阻止事件冒泡的兼容性解决方案 (了解)

  if(e && e.stopPropagation){
      e.stopPropagation();
  }else{
      window.event.cancelBubble = true;
  }

请简述事件委托

提示:「监听祖先元素」

  • 原理:利用事件冒泡原理,将子元素的操作委托给父元素或是祖先元素统一管理。
  • 用途:
  1. 当需要给后代元素执行多个重复事件时,可通过事件委托一次性管理操作来减少事件触发,节约内存。

  2. 动态监听元素:当需要给动态添加的元素添加事件时,必须通过事件委托来委托给父辈元素或祖先元素。