likes
comments
collection
share

JS深挖:事件机制答疑——注册事件监听、事件响应操作、冒泡和捕获

作者站长头像
站长
· 阅读数 20
目录:
1、事件机制概念
2、注册事件监听的方法
3、事件操作
4、冒泡和捕获

1、事件机制

问题描述:1)事件机制是如何起作用的?它跟事件循环机制有何区别?

答:事件机制区分于事件循环,它是用户交互层面的,依靠的是事件流。

Dom事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。

所以是浏览器时刻监听用户操作,一旦触发了事件,就会触发对应的事件流,这时候如果注册了事件监听函数,就会被触发。如果有多个事件同时触发,就会依次执行事件响应。

用户通过对固定元素注册事件监听的方法,来手动添加事件响应函数。


2、事件监听的方法

问题描述:1)几种方法?有何区别?2) addEventListner的第三个参数?

1)有三种事件监听方法HTML事件处理方法:特定元素支持的每个事件都可以使用事件处理程序的名字以 HTML 属性的形式来指定。此时属性的值必须是能够执行的 JavaScript 代码,正常会绑定为事件处理函数。这种方法最大的缺陷就是将HTML代码和JS代码混用,且当需要事件处理的元素非常多时,不适用。

<input type="button" value="Click Me" onclick="console.log('Clicked')"/>

Dom0事件处理方法:把一个函数赋值给一个事件处理程序属性,它的最大局限是,一个事件只能绑定一个事件处理,若绑定多个,那么后面的会覆盖前面的。

let btn = document.getElementById("myBtn"); 
btn.onclick = function() { 
    console.log(this.id); // "myBtn" 
};

Dom2事件处理程序:定义了两个方法:addEventListener()和 removeEventListener()。这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:事件名、事件处理函数和一个布尔值,true 表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事件处理程序。

与方法2不同,addEventListener 可以给一个事件注册多个listener。

let btn = document.getElementById("myBtn"); 
btn.addEventListener("click", () => { 
   console.log(this.id); 
}, false);

需要注意的是,removeEventListener的几个参数,必须与addEventListener的保存完全一致,才能够取消监听。

let btn = document.getElementById("myBtn"); 
let handler = function() { 
   console.log(this.id); 
}; 
btn.addEventListener("click", handler, false); 
// 取消
btn.removeEventListener("click", handler, false); // 有效果!

2)addEventListener的第三个参数在旧版本的DOM规定中,第三个参数默认规定为设置当前事件监听是在冒泡(默认)/捕获阶段执行,它是一个boolean值,默认为false。但是实际目前第三个参数已经有更复杂的配置,它设置为一个叫option的对象,可用选项如下:JS深挖:事件机制答疑——注册事件监听、事件响应操作、冒泡和捕获


3、事件操作

问题描述1)事件处理的event对象是什么?能获取哪些信息?

答:无论是哪种监听方法,event是传给事件处理程序的唯一变量,称为事件对象。事件对象包含与特定事件有关的属性和方法,其内容视情况不同。但是event事件对象固定包含一些公共属性和方法。JS深挖:事件机制答疑——注册事件监听、事件响应操作、冒泡和捕获JS深挖:事件机制答疑——注册事件监听、事件响应操作、冒泡和捕获


4、冒泡和捕获

问题描述:1)如果祖先元素的事件处理已经被捕获,那么子孙还会触发事件监听嘛?2)捕获和冒泡各自解除默认行为的方法?

1)答案是肯定的由于事件流三个阶段是固定的,也就是无论是否绑定事件监听和处理,事件都会在事件流的三个阶段经过所有涉及到的元素,阻止的方法只有手动的添加阻止默认行为。

2)阻止默认行为的方法使用event.stopPropagation()可以阻止冒泡和捕获阶段的默认行为,让后续的元素不受影响。

<script>
    let ul = document.getElementsByClassName('ulList');
    let li1 = document.getElementsByClassName('first');

    console.log('ul', ul);
    ul[0].addEventListener('click', (event) => {
      event.stopPropagation();
    }, false)

    li1[0].addEventListener('click', (event) => {
      console.log(event.target);
    }, false)
</script>

另外补充一下,想要阻止元素本身的默认事件响应行为,得用event.preventDefault(),如标签的跳转行为等。

let a = document.getElementById('alink');
a.addEventListener('click', (e) => {
      e.preventDefault();
})