CKEditor5事件系统源码分析(三)

上一节我们分析了事件系统的关键类EmitterMixin
的fire()方法,今天我们看看另一个方法就是delegate()
这个方法的代码如下:
delegate( ...events ) {
return {
to: ( emitter, nameOrFunction ) => {
if ( !this._delegations ) {
this._delegations = new Map();
}
// Originally there was a for..of loop which unfortunately caused an error in Babel that didn't allow
// build an application. See: https://github.com/ckeditor/ckeditor5-react/issues/40.
events.forEach( eventName => {
const destinations = this._delegations.get( eventName );
if ( !destinations ) {
this._delegations.set( eventName, new Map( [ [ emitter, nameOrFunction ] ] ) );
} else {
destinations.set( emitter, nameOrFunction );
}
} );
}
};
}
这个方法就比较简单,首先,我们需要一个代理映射,这个代理映射是一个map,它的key显然是事件名称,而value值又是一个map,这个map的key是emitter,value是事件名称或者一个函数。
实际上在调用这个delegate方法的时候,本质上就是存储一些数据结构,而这个结构是有一个两层的map来构建的。
这样在fire的时候,先取出这些map,然后再调用一个方法就是fireDelegatedEvents
下面我们看看这个方法:
fireDelegatedEvents( destinations, eventInfo, fireArgs ) {
for ( let [ emitter, name ] of destinations ) {
if ( !name ) {
name = eventInfo.name;
} else if ( typeof name == 'function' ) {
name = name( eventInfo.name );
}
const delegatedInfo = new EventInfo( eventInfo.source, name );
delegatedInfo.path = [ ...eventInfo.path ];
emitter.fire( delegatedInfo, ...fireArgs );
}
}
首先会跌倒这个事件对应的map,实际上就是一个一个的<emitter,name>对,然后构造具体的事件,这个通过代码const delegatedInfo = new EventInfo( eventInfo.source, name );
,然后配置path,最后调用fire出发事件,迭代完map实际上就是执行所有的代理功能。
好了,这个方法挺简单的,至于取消代理的方法就不用分析了,本质上就是删除两层map中的一些值。