CKEditor5事件系统
最近在学习CK5,一种最大的感受就是CK5的架构不是很大,但是内容特别多。笔者在学习中,总结出一个浅显的道理,那就是
掌握基础知识,对框架宏观把握,学习起来会事半功倍。
今天开始初步研究一下CK5的事件系统:
在CK5的事件系统中,关键的一个对象被称作Emitter(发射器),Emitter是一个可以发送事件的对象。如何创建一个Emitter,下面的代码创建了一个混合了事件发送的AnyClass类,它实例化以后就是一个可以发送事件的Emitter对象
import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
import mix from '@ckeditor/ckeditor5-utils/src/mix';
class AnyClass {
// ...
}
mix( AnyClass, EmitterMixin );
上面的代码来自CK5的官网,分析以上代码,可以看出核心的类有两个,一个是EmitterMixin
,另一个是mix
。
不难看出:
第一个类EmitterMixin
是实现了事件系统的核心类,而<i><strong>mix</strong></i>
方法只是将事件系统核心功能复制到具体类。
Emitter的On和Off分析
以上代码中AnyClass就是一个具有监听和发送时间的类,因此可以有以下代码:
Const anyClass = new AnyClass();
anyClass.on( 'eventName', ( eventInfo, ...args ) => { ... } );
这个anyClass对象就可以监听一个名为eventName的事件,一旦触发(anyClass.fire('eventName'))这个事件,那么就会执行后面的回调函数。
再次用另一段代码来说明问题
splitButtonView.on( 'execute', () => {
editor.execute( 'newCodeBlock', {
usePreviousLanguageChoice: true
} );
editor.editing.view.focus();
} );
看到了吧,这段代码的意思是,一旦在splitButtonView触发execute事件,那么就会执行回调函数。这里需要注意的是:
- splitButtonView是一个Emitter对象
- 触发事件只能在这个splitButtonView对象上,也就是自己监听自己
如果要移除监听呢?
AnyClass.off( 'eventName', handler );
简单吧。
Emitter的listenTo和stopListening分析
CK5还提供了另一种监听方式:
const anyClass = new AnyClass();
//注意,这里假定AnotherClass也是一个Emitter
const anotherClass = new AnotherClass();
AnyClass.listenTo( anotherClass, 'eventName', ( eventInfo, ...args ) => { ... } );
这里的意思就是emitter:anyClass 监听 emitter:anotherClass上的eventName事件,如果后者(anotherClass.fire('eventName'))触发了这个事件,那么回调函数会立即执行。
this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
console.log('clipboardInput');
let insertionRange = model.createRange( model.document.selection.anchor );
// Use target ranges in case this is a drop.
if ( data.targetRanges ) {
insertionRange = editor.editing.mapper.toModelRange( data.targetRanges[ 0 ] );
}
if ( !insertionRange.start.parent.is( 'element', 'newCodeBlock' ) ) {
return;
}
const text = data.dataTransfer.getData( 'text/plain' );
const writer = new UpcastWriter( editor.editing.view.document );
// Pass the view fragment to the default clipboardInput handler.
data.content = rawSnippetTextToViewDocumentFragment( writer, text );
} );
上面的代码我是从一个插件类中摘取出来的,this就代表这个插件类,而这个插件类会监听这个对象:
editor.editing.view.document
而监听的事件是剪贴板在视图文档的输入,其实说人话就是当我们复制一些内容到CK5的内容去的时候,这个插件的回调函数就会执行。
类似的原理,如果想移除对某个emitter的监听:
const anyClass = new AnyClass();
//注意,这里假定AnotherClass也是一个Emitter
const anotherClass = new AnotherClass();
// Stop listening to a specific handler.
anyClass.stopListening( anotherClass, 'eventName', handler );
// Stop listening to a specific event.
anyClass.stopListening( anotherClass, 'eventName' );
// Stop listening to all events fired by a specific emitter.
anyClass.stopListening( anotherClass);
// Stop listening to all events fired by all bound emitters.
anyClass.stopListening();
通过以上介绍,我想大家应该明白emitter的on和listenTo方法的区别和如何使用了吧,以及stopListening()方法的使用。
总结一下:
1、emitter的on方法绑定的函数是通过自身来触发的。
2、emitter的listenTo方法是通过其他emitter来触发的。
3、stopListening()解除绑定的函数,是否有参数决定解除绑定的粒度问题。