JavaScript Events
2018-03-02
浏览器中的事件。
基本使用
1 | var button = document.getElementById("createButton"); |
- 当监听事件的函数为匿名时, 由于我们没有该匿名函数的reference, 我们无法通过
removeEventListener()
取消该事件监听。 - 监听函数获得
event
对象,它包含了这个事件的相关信息,如timestamp, coordinates, 触发事件的对象(target),还有相关的function。
事件的触发顺序
如果该元素和其父元素拥有相同的事件监听,当这个事件被触发时,哪个事件监听首先执行呢 ?
对于这个问题,网景公司和微软采取了两种不同的处理方式。
事件捕获(Netscape): 由外而内
- 当某元素触发某个事件时(如Click), 顶层对象document会发出一个事件流,随着DOM树节点向目标节点流去,经过的节点如果绑定了 特定的在捕获阶段触发的事件监听器 ,则该事件监听器被触发,事件流最终流向目标节点。
事件冒泡(Microsoft): 由内到外
- 从目标元素开始,往顶层元素传播。途中如果经过的节点绑定了 在冒泡阶段触发的事件监听器,则该监听器被触发,事件流最终流向顶层document对象。可以使用
event.stopPropagation()
终止冒泡过程。
W3C标准: 由外到内再到外
取消事件
在事件捕获和冒泡阶段中,可以通过
event.stopPropagration()
来取消事件的进一步传播1
2
3
4
5let button = document.getElementById('click');
button.addEventListener('click', function(e){
e.stopPropagation();
/*...*/
});同一元素绑定针对相同事件的多个EventHandler, EventHanlder按照其绑定顺序被执行; 如果其中的一个 EventHandler A 执行了
event.stopImmediatePropagation()
,那么不仅事件传播停止,顺序在A之后的其他 EventHandler 也不会被执行。
Event 对象
- 传入
EventHanlder()
的Event对象的属性可以分为以下几个类型:- 规定事件类型: bubbles
- 关于事件执行环境的属性: button, ctrlKey, altKey…
- 与按键事件有关的属性:charCode, keyCode, which…
- 事件的触发位置: pageX, pageY, screenX, screenY…
- 与事件相关的元素: target, originalTarget,currentTarget, realtedTarget
- 事件传播:
stopPropagation()
,stopImmediatePropagation
- 默认行为:
preventDefault()
上下文(context)变化
当使用
addEventListener()
添加的事件监听被触发时,事件处理函数中的this
被修改为指向目标元素。通过如下方法保存原始上下文:
1
2
3
4
5
6
7
8
9
10
11
12
13function proxy(func, thisObject){
return (function(){
return func.apply(thisObject, arguments);
});
}
var clicky = {
wasClicked: function(){},
addListeners: function(){
var self = this;
document.getElementById('id').addEventListeners(proxy(self.wasclick, this));
}
}
事件委派
- 由于事件的冒泡机制, 我们可以仅仅在元素的父元素上添加EventHanlder来监听所有子元素的事件。
- 可以减少代码量
- 动态添加地子元素仍然会拥有该事件监听器
1 | // Delegating Events on a ul list |
自定义事件
通过 jQuery 创建自定义事件
1
2
3
4//Bind custom event
$('.class').bind('refresh.widget',function(){});
//Trigger Custom event
$('.class').trigger('refresh.widget');通过 Event 构造函数创建自定义事件
1
2
3
4
5
6
7
8var event = new Event('build');
var eventWithData = new CustomEvent('build',{ 'detail': ele.dataset.time });
// Listen for the event
element.addEventListener('build', function(e){ /**/ });
// Dispatch the event
element.dispatchEvent(event);通过自定义事件实现的jQuery Tab Plug-ins
1
2
3
4
5
6
7
8<ul id='tabs'>
<li data-tab="users">Users</li>
<li data-tab="groups">Groups</li>
</ul>
<div id='tabsContent'>
<div data-tab='users'>...</div>
<div data-tab='group'>...</div>
</div>
1 | jQuery.fn.tabs = function(control){ |
- 通过Javascript 实现
1 | var element = document.getElementById('tabs'); |
非DOM事件
- Publish / Subscribe模式: Pub / Sub 是一种沟通模式, Publisher向某一特定频道发送消息。 当消息被发送时,订阅了该频道的Subscriber收到通知。
- Publisher 和 Subscriber是完全分离的。它们只是享有一个共同的频道。
1 | var PubSub = { |