要分析框架的源码,首先需要从基类开发,在Openlayers
中BaseObject
可以说是很多类的基类,比如Map
,View
,Layer
,Overlay
等这些类,都 是继承于BaseObject
,就先从BaseObject
这个类来开始看。BaseObject
并不是最顶端的基础,也是继承于其它的类,继承关系如下所示:
Disposable》Target》Observable》BaseObject
下面就这几个类来进行分析。
1.Disposable
Disposable
可以说是所有相关类的老祖宗,该类的代码很简洁,提供的方法也就两个。分别是dispose()
和disposeInternal()
。该类的主要作用是清除对象和事件等信息,一般在子类通过重写disposeInternal()
方法处理清空的逻辑,调用dispose()
来执行清除的操作。
2.Target
Target
是一个目标对象,主要用于管理相关的事件,添加事件,移除事件、派发事件等操作都是使用该类来处理。
2.1构造函数
Target 的构造函数主要是用于实例化pendingRemovals_
,dispatching_
,dispatching_
等属性,定义属性的时候在属性名后面加了下划线表示为私有变量。
constructor(opt_target) {
super();
/**
* @private
* @type {*}
* 参数信息
*/
this.eventTarget_ = opt_target;
/**
* @private
* @type {!Object<string, number>}
* 待删除的事件
*/
this.pendingRemovals_ = {};
/**
* @private
* @type {!Object<string, number>}
* 派发中的事件
*/
this.dispatching_ = {};
/**
* @private
* @type {!Object<string, Array<import("../events.js").ListenerFunction>>}
* 所有事件
*/
this.listeners_ = {};
}
2.2添加事件
添加事件的逻辑为先根据type
从listeners_
中获取,如果没被添加过,就先初始化数组,然后再进行添加。
addEventListener(type, listener) {
if (!type || !listener) {//type和listener不能为空
return;
}
let listeners = this.listeners_[type];
if (!listeners) {//为空时初始化数组
listeners = [];
this.listeners_[type] = listeners;
}
if (listeners.indexOf(listener) === -1) {
listeners.push(listener);
}
}
2.3事件派发
使用dispatchEvent
可以对事件进行派发,派发完成后,执行removeEventListener
进行删除。
删除事件
该方法主要是通过type
和listener
将listeners_
中对应的事件删除。
removeEventListener(type, listener) {
const listeners = this.listeners_[type];
if (listeners) {
const index = listeners.indexOf(listener);
if (index !== -1) {
if (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];
}
}
}
}
}
dispatchEvent(event) {
//判断event类型
const evt = typeof event === 'string' ? new Event(event) : event;
const type = evt.type;
if (!evt.target) {//找到事件的上档对象
evt.target = this.eventTarget_ || this;
}
const listeners = this.listeners_[type];
let propagate;
if (listeners) {
if (!(type in this.dispatching_)) {//判断有没有正在派发的
this.dispatching_[type] = 0;
this.pendingRemovals_[type] = 0;
}
++this.dispatching_[type];//开始派发事件
for (let i = 0, ii = listeners.length; i < ii; ++i) {
if (listeners[i].call(this, evt) === false || evt.propagationStopped) {
propagate = false;
break;
}
}
--this.dispatching_[type];//事件派发结束
if (this.dispatching_[type] === 0) {
let pendingRemovals = this.pendingRemovals_[type];
delete this.pendingRemovals_[type];
while (pendingRemovals--) {//移除事件
this.removeEventListener(type, VOID);
}
delete this.dispatching_[type];
}
return propagate;
}
}
3.Observable
Observable
是一个观察者对象,这里主要运行了设计模式中的观察者模式,用于订阅和发布事件,该类主要包括on
,once
,un
等方法。
3.1on
用于添加事件,主要是使用listen
方法来调用Target
类的addEventListener
来添加。
on(type, listener) {
if (Array.isArray(type)) {//数组,多个事件使用的是同一个函数回调
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {//遍历数组进行添加
keys[i] = listen(this, type[i], listener);
}
return keys;
} else {
return listen(this, /** @type {string} */ (type), listener);
}
}
3.2once
同样的事件类型不能重复添加。
once(type, listener) {
if (Array.isArray(type)) {
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {
keys[i] = listenOnce(this, type[i], listener);
}
return keys;
} else {
return listenOnce(this, /** @type {string} */ (type), listener);
}
}
3.3 un
用于删除事件,主要调用Target
类的removeEventListener
来移除事件。
un(type, listener) {
if (Array.isArray(type)) {
for (let i = 0, ii = type.length; i < ii; ++i) {
this.removeEventListener(type[i], listener);
}
} else {
this.removeEventListener(type, listener);
}
}
4.BaseObject
BaseObject
主要用于往对象中动态添加属性和属性值,在初使化的时候,可以通过构造函数来传递默认添加的对象,然后调用setProperties
给values_
赋值,如下所示:
constructor(opt_values) {
super();
getUid(this);
this.values_ = {};
if (opt_values !== undefined) {//设置属性
this.setProperties(opt_values);
}
}
setProperties(values, opt_silent) {
for (const key in values) {
this.set(key, values[key], opt_silent);
}
}
在调用set
方法的时候,其中一个流程用到了notify
方法,使用该方法可以通知属性的变化,如下所示:
set(key, value, opt_silent) {
if (opt_silent) {
this.values_[key] = value;
} else {
const oldValue = this.values_[key];
this.values_[key] = value;
if (oldValue !== value) {
this.notify(key, oldValue);
}
}
}
notify(key, oldValue) {
let eventType;
eventType = getChangeEventType(key);
//派发‘change:属性名’的事件
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
eventType = ObjectEventType.PROPERTYCHANGE;
//派发PROPERTYCHANGE事件
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
}
getProperties() {
return assign({}, this.values_);//复制一个新的对象返回
}
BaseObject
先分析到此了,代码一路看下来,不得不说这个框架的代码写的很好,很简洁,很有参考价值,设计模式也用的很到位,值得慢慢品味。真香!
个人博客