走进基础:事件、事件模型、事件处理机制
引入
博客面向对象3个人啦。哈哈哈。你知道addEventListern接受的第三个参数吗?
1 |
|
摘录mdn, 第三个参数可为obj或者boolean。仅为扩充理论知识。也来效仿一下无问东西,指明中心跟着图这个中心思想走。
Dom标准级别(摘抄)
首先要明确一下这个概念,DOM有4次版本更新,与DOM版本变更,产生了3种不同的DOM事件定义 DOM0级、DOM2级、DOM3级。由于DOM1级中没有事件的相关内容,所以没有DOM1级事件。
- Dom 0级模型。在html中直接绑定事件或者声明onclick
1 | <div onclick=""></div> |
- Dom 2级模型。即addEventListener
1 | addEventListener(eventType, handler, useCapture) |
DOM浏览器中可能发生的事件有很多种,不同事件类型具有不同的信息,DOM3级事件规定了一下几种事件:
UI事件,当用户与页面上的元素交互时触发;
焦点事件,当元素获得或者失去焦点时触发;
鼠标事件,当用户通过鼠标在页面上执行操作时触发;
滚轮事件,当使用鼠标滚轮(或类似设备)时触发;
文本事件,当在文档中,输入文本时触发;
键盘事件,当用户通过键盘在页面上执行操作时触发;
合成事件,当为IME(Input Method Editor,输入法编辑器)输入字符时触发;
变动事件,当底层Dom结构发生变化时触发;
DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件。包括IE9在内的主流浏览器都支持DOM2级事件,IE9也支持DOM3级事件。
DOM3级还定义了自定义事件CustomEvent。
事件
JS的事件模型可以说是一种观察者模式的被观察者。刚打开mdn,晕了。event千千万,我看到他们认识就ok了。最近做一个clibboard的功能封装对ClipboardEvent很感兴趣。
Event接口表示在DOM中发生的任何事件。事件处理函数可以附加在各种对象,event被创建传递给监听器。(可以看到该eventTarget会有evnet listeners哟)知识点总结来了。
- 在mdn上千万的event基本上都是Event的子类。(ClipboardEvent, keyboardEvent…)
本身的实例属性和成员方法有对冒泡传播阶段等的一些介绍。
target 和 currentTarget的区别? 一直弄混呀!target是调用事件的dom元素。currentTarget是其事件监听器当前正在被处理的元素节点。当事件捕获和冒泡发生时,这个值就会改变。
1
2
3
4
5
6
7
8
9
10
11
12/**
* 第一个输出的是inner dom
* 第二个输出的事outer dom
*/
// html
<div class="outer"> <div class="inner"></div> <div>
//js
let el = document.querySelector('.outer');
el.addEventListener('click', (e) => {
console.log(e.target);
console.log(e.currentTarget);
}, false)
关于常见的Event.preventDefault()、Event.stopImmediatePropagation()
、Event.stopPropagation()的理解。后两者跟续在事件模型。- Event.preventDefault 取消浏览器对当前事件的默认行为。例如阻止checkbox的选择、a连接的跳转等。
- Event.stopPropagation 阻止冒泡。
Event.stopImmediatePropagation 阻止同一个事件被其他函数监听调用(暴力解决一切)。
1
2
3
4
5
6
7
8// stop checkbox 即不能处罚默认选中的行为
// html
<input type="checkbox" id="check">
// js
let el = document.querySelector('#check');
el.addEventListener('click', (el) => {
el.preventDefault();
}, false);
创建一个自定义事件
1
2var build = new Event('test');
el.addEventListener('test', () => {});
事件模型
如大家周知捕获和冒泡。对于事件流则是捕获到目标元素再到冒泡。对于传播方向是到哪个节点需要看一下w3c规范的传播图即可得知。
1 | // flag置为true或false 看捕获和冒泡的输出。 |
1 | // 看捕获和冒泡同时的输出。 |
接着要看一下Event stopPropagation、stopImmediatePropagation的功效了。
1 | ['html', 'body', 'p', 'a'].forEach(targetName => { |
可以看出stopPropagation不仅可以阻止冒泡还可以阻止捕获,其实也可以阻止处于目标阶段。
1 | ['html','body','div','p','a'].forEach( item => { |
stopImmediatePropagation只要执行到绑定在当前事件源的事件的该语句,就不再执行其他监听函数。
事件委托
事件委托就是把一个或一组事件委托到它的外层元素。绑定事件即在最外层元素,通过事件流的冒泡机制触发每个子元素的事件。生活中的例子就是四个朋友排队买票,这四个朋友可以委托年龄最大的人买票。
- 优点
- 减少内存消耗
- 便于动态加载事件
- 一次委托,终身受用
- 缺点
- 有些事件例如blur没有冒泡的行为
- 还有些高频率事件mouseover等耗性能
这里面的stopImmediatePropagation和自定义事件都是dom3标准级别添加的。