EventTarget类
# 概述
EventTarget
类是 Openlayers 中许多类实现的基类,主要和事件监听触发有关。
# 源码剖析
# Disposable
类
EventTarget
类继承于Disposable
类,其实现如下:
class Disposable {
constructor() {
this.disposed = false;
}
dispose() {
if (!this.disposed) {
this.disposed = true;
this.disposeInternal();
}
}
disposeInternal() {}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
Disposable
类中定义了一个disposed
变量,默认值为false
,两个方法dispose()
和disposeInternal()
。
dispose
译为处置,由此推定Disposable
类就是用于在函数调用后执行某些clean up
操作。
# Target
类
EventTarget
类即target
实现如下:
class Target extends Disposable {
constructor(target) {
super();
this.eventTarget_ = target;
this.pendingRemovals_ = null;
this.dispatching_ = null;
this.listeners_ = null;
}
addEventListener(type, listener) {
if (!type || !listener) {
return;
}
const listeners = this.listeners_ || (this.listeners_ = {});
const listenersForType = listeners[type] || (listeners[type] = []);
if (!listenersForType.includes(listener)) {
listenersForType.push(listener);
}
}
dispatchEvent(event) {
const isString = typeof event === 'string';
const type = isString ? event : event.type;
const listeners = this.listeners_ && this.listeners_[type];
if (!listeners) {
return;
}
const evt = isString ? new Event(event) : /** @type {Event} */ (event);
if (!evt.target) {
evt.target = this.eventTarget_ || this;
}
const dispatching = this.dispatching_ || (this.dispatching_ = {});
const pendingRemovals =
this.pendingRemovals_ || (this.pendingRemovals_ = {});
if (!(type in dispatching)) {
dispatching[type] = 0;
pendingRemovals[type] = 0;
}
++dispatching[type];
let propagate;
for (let i = 0, ii = listeners.length; i < ii; ++i) {
if ('handleEvent' in listeners[i]) {
propagate = /** @type {import("../events.js").ListenerObject} */ (
listeners[i]
).handleEvent(evt);
} else {
propagate = /** @type {import("../events.js").ListenerFunction} */ (
listeners[i]
).call(this, evt);
}
if (propagate === false || evt.propagationStopped) {
propagate = false;
break;
}
}
if (--dispatching[type] === 0) {
let pr = pendingRemovals[type];
delete pendingRemovals[type];
while (pr--) {
this.removeEventListener(type, VOID);
}
delete dispatching[type];
}
return propagate;
}
disposeInternal() {
this.listeners_ && clear(this.listeners_);
}
getListeners(type) {
return (this.listeners_ && this.listeners_[type]) || undefined;
}
hasListener(type) {
if (!this.listeners_) {
return false;
}
return type
? type in this.listeners_
: Object.keys(this.listeners_).length > 0;
}
removeEventListener(type, listener) {
if (!this.listeners_) {
return;
}
const listeners = this.listeners_[type];
if (!listeners) {
return;
}
const index = listeners.indexOf(listener);
if (index !== -1) {
if (this.pendingRemovals_ && type in this.pendingRemovals_) {
// make listener a no-op, and remove later in #dispatchEvent()
listeners[index] = VOID;
++this.pendingRemovals_[type];
} else {
listeners.splice(index, 1);
if (listeners.length === 0) {
delete this.listeners_[type];
}
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# EventTarget
变量
EventTarget
类接受一个名为target
的参数,有四个私有变量,如下:
eventTarget_
:保存参数target
pendingRemovals
:对象,记录待移除的监听事件数量dispatching_
:对象,记录待派发的事件数量listeners_
:对象,键值分别对应事件类型和监听事件(回调函数)
# EventTarget
方法
addEventListener
addEventListener
方法就是注册事件监听到变量this.listeners_
中,且同一类型的同一个监听事件只添加一次,键值对分别对应事件类型和事件数组。
dispatchEvent
dispatchEvent
方法主要就是用来派发事件或者是触发回调,接受一个event
参数。
其原理是:
第一步:先检查参数
event
的类型,若它是一个字符串,则表示它是一个type
,否则将它的type
属性作为type
,以此来判断this.listeners_
中是否注册过该type
的监听,若不存在,则return
;否则进行第二步骤第二步:若参数
event
是一个字符串,则调用Event
类,实例化一个evt
;否则,evt
的值就是event
;然后确定evt.target
,若this.eventTarget_
存在,则evt.target
取值就是它,否则就是this
第三步:初始化
this.dispatching_[type]
和this.pengdingRemovals_[type]
的值为0,然后this.dispatching_[type]
自增1
第四步:定义一个变量
propagate
,用来标记事件是否继续传播;然后遍历this.listener_[type]
,若handleEvent
方法包含在注册事件中,则执行注册事件的handleEvent
方法,参数为evt
,返回值赋值给propagate
变量;若注册事件中不包含handleEvent
方法,则调用call
方法执行该注册事件,参数为evt
,返回值赋值给propagate
变量;最后判断propagate
的值和evt.propagationStopped
,若propagate
为false
,则propagate
赋值为false
;若propagate
为true
,则当evt.propagationStopped
为true
时,propagate
才为false
,退出循环。第五步:注册事件执行完后,调用
this.removeEventListener
清除第六步:最后返回变量
propagation
disposeInternal
disposeInternal
方法就是将this.listeners
置空,clear
方法用于清除删除对象上的所有可枚举的属性,其实现如下
export function clear(object) {
for (const property in object) {
delete object[property];
}
}
2
3
4
5
getListeners
getListeners
方法就是根据type
获取对应的事件数组,若不存在则返回undefined
hasListeners
hasListeners
方法用于判断this.listeners_
中是否存在type
,若存在则返回true
,否则判断this.listeners_
中是否存在其它类型的监听
removeListener
removeListener
方法用于移除注册的监听事件。该方法接受两个参数type
和listener
.
其原理是当this.listener_[type]
存在时,就判断this.listener_[type]
是否包含listener
,如果包含,则判断this.pengdingRemovals_[type]
的值是否为0
,若为0
,则调用splice
移除this.listener_[type]
中对应位置的listener
,若this.listener_[type]
的长度为0
,则删除this.listeners_
中对应的键值对;若this.pengdingRemovals_[type]
不为0,则将该注册事件置为空函数,索引值自增
# Event
类
在上面介绍dispatchEvent
时,提到通过new Event(event)
实例化一个evt
,其中Event
类如下:
class BaseEvent{
constructor(type){
this.propagationStopped;
this.defaultPrevented;
this.type = type;
this.target = null;
}
preventDefault() {
this.defaultPrevented = true;
}
stopPropagation() {
this.propagationStopped = true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Event
类就是定义了一个事件最基本的属性和方法
# 总结
本文介绍了EventTarget
类的几种方法和属性以及dispatchEvent
的核心原理,该方法在Openlayers中占据举重若轻的地位。