-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
JavaScriptJavaScriptJavaScript
Description
事件
事件模型
事件是JavaScript和HTML交互的方式,比如常用的click,blur,DOMContentLoaded,mousedown,mouseup事件等。我们会先订阅这些事件(被观察者),给事件指定事件处理程序,当事件发生时浏览器就会调用相应的处理程序进行处理。可以说,事件模型是观察者模式的具体实现。
事件处理机制
图片引用自官方文档

标准的DOM Events把事件传播分为三个阶段:
- 捕获阶段(Capture Phase)
- 处理目标阶段(At Target Phase)
- 冒泡阶段(Bubbling Phase)
由于IE在9以上才支持事件捕获,为了兼容性,我们更多让事件在冒泡阶段触发。
指定Event Handler(事件处理程序)的几种方式
Event Handler的名字:on<event>,比如onclick。
- HTML attribute
用元素与Event Handler同名的属性来指定,比如像下面这样
<input value="Click me" onclick="alert(this.value)" type="button" id="button">
a. 因为HTML属性时大小写不敏感的,这里onclick也可以写为onClick,ONCLICK,ONClick... 但还是建议使用lowercase.
b. 这种方式指定的事件处理程序会创建一个包含属性内容的函数,等价于
button.onclick = function(){
// this指向当前元素
alert(this.value);
// 可以取到event对象
alert(event.type);
}
// 这也提醒我们属性内容应该是一个函数调用c. 这种方式是不被推荐的。
2. DOM property(DOM0级事件处理程序)
<input id="elem" type="button" value="Click me">
<script>
var elem = document.getElementById('elem');
// 指定事件处理程序
elem.onclick = function() {
// this指向当前元素
alert(this.value);
// 可以取到event对象
alert(event.type);
};
// 删除事件处理程序
elem.onclick = null;
</script>a. DOM属性时大小写敏感的,所以属性只能写为onclick
b. 事件处理程序在冒泡阶段触发
c. 只能指定一个事件处理程序,否则会覆盖
3. addEventListener(DOM2级事件处理程序)
// 旧语法
target.addEventListener(type, listener[, useCapture]);- listener是函数,必需
- useCapture是可选值,默认为false。为true表示listener在捕获阶段触发,为false则表示在冒泡阶段触发
// 新语法
target.addEventListener(type, listener[, options]);- listener可以为函数,可以为对象(对象中实现了EventListener接口,即拥有handleEvent方法)
options对象为可选,包括如下几个选项capture默认为false,同上面的useCaptureonce默认为false,表示listener最多调用一次,触发后即被自动移除(Firefox50, Chrome55开始支持)passive默认为false,表示不会禁止事件的默认行为,即不会调用preventDefault方法(Firefox49,Chrome51开始支持)
passive是为了解决touch和wheel事件引起的滚动卡顿。因为touchstart,touchmove都是可以cancelable的,它们的默认行为是滚动页面,可以通过preventDefault阻止默认行为。不管是否阻止默认行为,浏览器会在执行事件处理程序后再执行默认行为,这就有可能造成滚动卡顿,即使事件处理程序是一个空函数。当设置{passive: true},浏览器在监听事件的时候就知道了事件处理程序不会调用preventDefault,浏览器就可以毫无顾虑的执行默认行为了。
a. 这种方式允许为同一个事件添加多个事件处理程序
b. 多个事件处理程序按照添加的顺序执行
removeEventListener(移除事件处理程序)
target.removeEventListener(type, listener[, options]);
target.removeEventListener(type, listener[, useCapture]);移除事件处理程序只检查type, listener, capture/useCapture,匿名的事件处理程序无法被移除。
element.addEventListener("mousedown", handleMouseDown, { passive: true });
element.removeEventListener("mousedown", handleMouseDown, { passive: true }); // Succeed
element.removeEventListener("mousedown", handleMouseDown, { capture: false }); // Succeed
element.removeEventListener("mousedown", handleMouseDown, { capture: true }); // Fail
element.removeEventListener("mousedown", handleMouseDown, { passive: false }); // Succeed
element.removeEventListener("mousedown", handleMouseDown, false); // Succeed
element.removeEventListener("mousedown", handleMouseDown, true); // Fail- IE事件处理程序
//添加事件处理程序
target.attachEvent(eventNameWithOn, callback);
elem.attchEvent('onclick', function(){
// this是window, 不是element
console.log(this===window); // true
});
//删除事件处理程序
target.detachEvent(eventNameWithOn, callback);a. 可以为同一事件添加多个事件处理程序
b. 多个事件处理程序会以与添加顺序相反的顺序执行
参考资料
Metadata
Metadata
Assignees
Labels
JavaScriptJavaScriptJavaScript