CKEditor5事件系统(事件优先级)

今天继续学习CK5的事件系统,上一节我们知道了怎么绑定和取消绑定事件的两种方法,知道在一个emitter上对一个同名事件可以绑定多个回调函数,自然问题来了,这些函数的执行顺序是怎么样的呢?

CK5的事件监听优先级

实际上,对于一个同名事件,CK5提供了事件优先级功能,如下代码所示

AnyClass.on( 'eventName', ( eventInfo, ...args ) => { console.log('execute event one') } );
AnyClass.on( 'eventName', ( eventInfo, ...args ) => { console.log('execute event two') } );
AnyClass.on( 'eventName', ( eventInfo, ...args ) => { console.log('execute event three') } );
AnyClass.fire('eventName')

这里没有指定优先级的情况下,谁先绑定,那么就谁先执行。CK5为了解决自定义执行的问题,在绑定的时候,提供了第三个参数priority:

AnyClass.on( 'eventName', ( eventInfo, ...args ) => 
    { console.log('execute event one') } ,{ priority: 'high' });
AnyClass.on( 'eventName', ( eventInfo, ...args ) => { console.log('execute event two') },        
	,{ priority: 'low' }
);
AnyClass.on( 'eventName', ( eventInfo, ...args ) => { console.log('execute event three') } 				,	,{ priority: 'highest' }
);
AnyClass.fire('eventName')

因此,有了优先级这个参数,我们对回调函数的执行,有了更多的控制:

CK5的事件系统总共提供了5个优先级:

  • highest
  • high
  • normal
  • low
  • lowest

注意:如果任何一个事件监听器停止执行,那么其他监听器都不会被执行,包括那些优先级较低的监听器。

CK5监听器阻止执行

this.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute low');
 },{priority: 'low'});


this.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute high');
},{priority: 'high'});


this.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute highest');
},{priority: 'highest'});

//另外一个是监听粘贴功能的代码
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.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute highest');
    console.log(evt.name);
    console.log(evt.source);
    evt.stop();
},{priority: 'highest'});

这时打印出来的日志如下:

而级别为high的监听器没有执行,只有最高界别的代码执行。同样的,我们还可以获取事件的名字和事件的源头。

this.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute highest');
    evt.return = 'return value';
},{priority: 'highest'});

事件还可以有一个返回值,当所有监听器执行完成后,fire方法可以或者这个返回值。

监听命名空间事件

命名空间事件是使用:来实现的

这里我们使用上一节定义的来AnyClass来说明这个问题:

import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
import mix from '@ckeditor/ckeditor5-utils/src/mix';
export default class AnyClass {
    // ...
}
mix( AnyClass, EmitterMixin );

这里我只用剪贴板的复制功能来验证命名空间事件的使用

this.listenTo(editor.editing.view.document, 'clipboardInput',( evt, data ) =>{
    console.log('execute highest');
    evt.return = 'return value';
    let anyClass = new AnyClass();
    anyClass.on( 'foo', () => { console.log('foo'); } );
    anyClass.on( 'foo:bar', () => { console.log('foo:bar'); } );
    anyClass.on( 'foo:bar:baz', () => { console.log('foo:bar:baz'); } );
    anyClass.fire('foo');
    anyClass.fire('foo:bar');
},{priority: 'highest'});

从这里可以看到如果只发出fire('foo'),那么只有一个监听器执行,而如果发出fire('foo:bar'),那么有两个监听器执行。因此如果在文档中有一个insert:p事件,那么既可以监听insert事件,也可以监听insert:p事件。这样的好处不言而喻。

下一节,我们研究事件的代理。

版权声明:著作权归作者所有。

相关推荐

Angular使用keydown监听tab键事件处理

在html中,在焦点元素上按下tab键,它会跳到下一个可聚焦元素(按钮、输入等)。如果监听的是keyup,当按下tab放开时,焦点元素已经变为下一个可聚焦元素。在前面的焦点元素上做监听keyup是不会触发事件的处理handler的。为了避免焦点元素的变化这个问题,可以使用keydown监听tab键。Angular监听tab键示例示例:<input (keydown.Tab)="onKey($

JavaScript 点击事件只执行一次的方法

JavaScript要实现只允许Button被点击执行一次的办法有几种:方法一、在添加事件监听器时,设置选项once为true示例:<div id="btn0"> My button</div><script> function doSomething(v) { console.log(v); } document.getE

RecyclerView添加点击事件监听器

实现RecyclerView.OnItemTouchListener的项目触摸监听器:import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.M

JavaScript:给动态元素绑定事件

JavaScript给动态添加的元素绑定事件有几种方式:方法一:jQuery使用jQuery.fn.on可以很简单为动态元素绑定事件:$(staticAncestors).on(eventName, dynamicChild, function() {}); staticAncestors:静态的祖先元素选择器eventName:事件名,如click等dynamicC

[译]代码优先的Java 9模块系统教程(二)

服务监控(ServiceMonitor)让我们来想象一个提供娱乐服务的网络,可能是社交网络或者是视频网络。我们希望监控这些服务,以确定系统的健康状况,并且在发生问题时能够发现,而不是客户报告。 这就是ServiceMonitor示例程序所要做的:监视这些服务(另一个惊喜)。幸运的是,服务已经收集了我们想要的数据,ServiceMonitor所需要做的就是定期查询。 不幸的是,并

[译]代码优先的Java 9模块系统教程(一)

Java平台模块系统(JPMS)将模块化带入Java和JVM,并改变了我们在大型应用中的编程方式。 为了充分利用它,我们需要很好地了解,第一步是学习基础知识。 在本教程中,我首先向你展示一个简单的Hello World示例,然后我们用Java 9将一个现有的demo程序模块化。我们将创建模块声明(module-info。java),使用模块路径来编译,打包,