Webcourse/13-前端面试/01-面试必看/03-DOM事件的总结.md
2020-04-19 18:24:43 +08:00

312 lines
7.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 前言
要学习事件的基础内容请看先本人之前的基础文章
- 04-JavaScript基础/27-事件对象Event
- 04-JavaScript基础/28-事件捕获和事件冒泡
- 04-JavaScript基础/29-事件委托
知识难度不大只是大家需要系统地学习
**知识点主要包括以下几个方面**
- 基本概念DOM事件的级别
面试不会直接问你DOM有几个级别但会在题目中体现请用DOM2 ....
- DOM事件模型DOM事件流
面试官如果问你**DOM事件模型**你不一定知道怎么回事其实说的就是**捕获和冒泡**
**DOM事件流**指的是事件传递的**三个阶段**
- 描述DOM事件捕获的具体流程
讲的是事件的传递顺序参数为false默认参数为true各自代表事件在什么阶段触发
能回答出来的人寥寥无几也许有些人可以说出一大半但是一字不落的人极少
- Event对象的常见应用Event的常用api方法
DOM事件的知识点一方面包括事件的流程另一方面就是怎么去注册事件也就是监听用户的交互行为第三点在响应时Event对象是非常重要的
- 自定义事件非常重要
一般人可以讲出事件和注册事件但是如果让你讲**自定义事件**能知道的人就更少了
- 事件委托
业务中经常用到
下面分别讲解
## DOM事件的级别
DOM事件的级别准确来说**DOM标准**定义的级别包括
**DOM0的写法**
```javascript
element.onclick = function () {
}
```
上面的代码是在 js 中的写法如果要在html中写写法是在onclick属性中 js 语句
**DOM2的写法**
```javascript
element.addEventListener('click', function () {
}, false);
```
重要上面的第三参数中**true**表示事件在**捕获阶段**触发**false**表示事件在**冒泡阶段**触发默认如果不写则默认为false
**DOM3的写法**
```javascript
element.addEventListener('keyup', function () {
}, false);
```
DOM3中增加了很多事件类型比如鼠标事件键盘事件等
PS为何事件没有DOM1的写法呢因为DOM1标准制定的时候没有涉及与事件相关的内容
**总结**关于DOM事件的级别能回答出以上内容即可不会出题目让你做
## DOM事件模型DOM事件流
### DOM事件模型
DOM事件模型讲的就是**捕获和冒泡**一般人都能回答出来
- 捕获从上往下
- 冒泡从下目标元素往上
### DOM事件流
DOM事件流讲的就是浏览器在于当前页面做交互时这个事件是怎么传递到页面上的
类似于Android里面的事件传递
完整的事件流分三个阶段
- 1捕获 window 对象传到 目标元素
- 2目标阶段事件通过捕获到达目标元素这个阶段就是目标阶段
- 3冒泡**目标元素**传到 Window 对象
![](http://img.smyhvae.com/20180306_1058.png)
![](http://img.smyhvae.com/20180204_1218.jpg)
## 描述DOM事件捕获的具体流程
> 很少有人能说完整
### 捕获的流程
![](http://img.smyhvae.com/20180306_1103.png)
**说明**捕获阶段事件依次传递的顺序是window --> document --> html--> body --> 父元素子元素目标元素
PS1第一个接收到事件的对象是 **window**有人会说body有人会说html这都是错误的
PS2JS中涉及到DOM对象时有两个对象最常用windowdoucument它们俩也是最先获取到事件的
代码如下
```javascript
window.addEventListener("click", function () {
alert("捕获 window");
}, true);
document.addEventListener("click", function () {
alert("捕获 document");
}, true);
document.documentElement.addEventListener("click", function () {
alert("捕获 html");
}, true);
document.body.addEventListener("click", function () {
alert("捕获 body");
}, true);
fatherBox.addEventListener("click", function () {
alert("捕获 father");
}, true);
childBox.addEventListener("click", function () {
alert("捕获 child");
}, true);
```
**补充一个知识点**
js中
- 如果想获取 `body` 节点方法是`document.body`
- 但是如果想获取 `html`节点方法是`document.documentElement`
### 冒泡的流程
与捕获的流程相反
## Event对象的常见 api 方法
用户做的是什么操作比如是敲键盘了还是点击鼠标了这些事件基本都是通过Event对象拿到的这些都比较简单我们就不讲了我们来看看下面这几个方法
### 方法一
```javascript
event.preventDefault();
```
解释阻止默认事件
比如已知`<a>`标签绑定了click事件此时如果给`<a>`设置了这个方法就阻止了链接的默认跳转
### 方法二阻止冒泡
这个在业务中很常见
有的时候业务中不需要事件进行冒泡比如说业务这样要求单击子元素做事件A单击父元素做事件B如果不阻止冒泡的话出现的问题是单击子元素时子元素和父元素都会做事件A这个时候就要用到阻止冒泡了
w3c的方法火狐谷歌IE11
```javascript
event.stopPropagation();
```
IE10以下则是
```javascript
event.cancelBubble = true;
```
兼容代码如下
```javascript
box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
```
上方代码中我们对box3进行了阻止冒泡产生的效果是事件不会继续传递到 fathergrandfatherbody了
### 方法三设置事件优先级
```javascript
event.stopImmediatePropagation();
```
这个方法比较长一般人没听说过解释如下
比如说我用addEventListener给某按钮同时注册了事件A事件B此时如果我单击按钮就会依次执行事件A和事件B现在要求单击按钮时只执行事件A不执行事件B该怎么做呢这是时候就可以用到`stopImmediatePropagation`方法了做法是在事件A的响应函数中加入这句话
大家要记住 event 有这个方法
### 属性4属性5事件委托中用到
```javascript
event.currentTarget //当前所绑定的事件对象。在事件委托中,指的是【父元素】。
event.target //当前被点击的元素。在事件委托中,指的是【子元素】。
```
上面这两个属性在事件委托中经常用到
**总结**上面这几项非常重要但是容易弄混淆
## 自定义事件
自定义事件的代码如下
```javascript
var myEvent = new Event('clickTest');
element.addEventListener('clickTest', function () {
console.log('smyhvae');
});
//元素注册事件
element.dispatchEvent(myEvent); //注意,参数是写事件对象 myEvent不是写 事件名 clickTest
```
上面这个事件是定义完了之后就直接自动触发了在正常的业务中这个事件一般是和别的事件结合用的比如延时器设置按钮的动作
```javascript
var myEvent = new Event('clickTest');
element.addEventListener('clickTest', function () {
console.log('smyhvae');
});
setTimeout(function () {
element.dispatchEvent(myEvent); //注意,参数是写事件对象 myEvent不是写 事件名 clickTest
}, 1000);
```
## 事件委托
参考本人这篇文章的最后一段
- 04-JavaScript基础/29-事件委托