美文网首页ckeditor5
ckeditor5/utils:如何设置observable

ckeditor5/utils:如何设置observable

作者: videring | 来源:发表于2020-09-21 15:50 被阅读0次

前置:
ckeditor5/utils:emittermixin(事件监听机制)
ckeditor5官网observables讲解
ckeditor5/utils:ObservableMixin

可观察的对象(Observables)是CKEditor 5 Framework的常见组成要素。
绑定到可观察对象的模板使得用户界面具有动态和交互式特质。一些基本类如Editor、Command可也是可观察对象。

export default class ButtonView extends View {
    constructor( locale ) {
        super( locale );
                // ......
        this.set( 'isEnabled', true );
        this.set( 'isOn', false );
        this.set( 'label' );
        this.set( 'isVisible', true );
        this.set( 'isToggleable', false );
        // ......
    }
}

如下代码,每当label属性改变后,change:label事件会被触发,相应的回调函数会被执行:

const view = new ButtonView();

view.on( 'change:label', ( evt, propertyName, newValue, oldValue ) => {
    console.log(
        `#${ propertyName } has changed from "${ oldValue }" to "${ newValue }"`
    );
} )

view.label = 'Hello world!'; // -> #label has changed from "undefined" to "Hello world!"
view.label = 'Bold'; // -> #label has changed from "Hello world!" to "Bold"

view.type = 'submit'; // Changing a regular property fires no event.
  • delegate:除了set方法外,还有其他方法如delegate等也可以用于设置属性为observable:
buttonFoo.delegate( 'execute' ).to( toolbar );
buttonBar.delegate( 'execute' ).to( toolbar );

toolbar.on( 'execute', evt => {
    console.log( `The "${ evt.source.label }" button was clicked!` );
} );
  • bind
// editor.commands.isEnabled必须使用set方法定义,才能保证bind方法的有效性
const button = new Button();
const command = editor.commands.get( 'bold' );

button.bind( 'isEnabled' ).to( command, 'isEnabled' );
  • decorate(装饰):
    通过decorate方法,可以将object methods转换为事件驱动性质的方法。当某个方法被decorate后,那么当方法被执行时,一个同名的事件将会被创建和触发。源码很简单,如下:
decorate( methodName ) {
        const originalMethod = this[ methodName ];

        if ( !originalMethod ) {
            throw new CKEditorError(
                'observablemixin-cannot-decorate-undefined',
                this,
                { object: this, methodName }
            );
        }

        this.on( methodName, ( evt, args ) => {
            evt.return = originalMethod.apply( this, args );
        } );

        this[ methodName ] = function( ...args ) {
            return this.fire( methodName, args );
        };
}

实例如下:

class Button extends View {
    constructor() {
        // ...
        this.decorate( 'focus' ); // 注意这里!!!
    }

    focus( force ) {
        console.log( `Focusing button, force argument="${ force }"` );

        // Unless forced, the button will only focus when not already focused.
        if ( force || document.activeElement != this.element ) {
            this.element.focus();

            return true;
        }

        return false;
    }
}

// Cancelling the execution
const button = new Button();

// Render the button to create its #element.
button.render();

// The logic controlling the behavior of the button.
button.on( 'focus', ( evt, [ isForced ] ) => {
    // Disallow forcing the focus of this button.
    if ( isForced === true ) {
        // 参见:[ckeditor5/utils:emittermixin(事件监听机制)](https://www.jianshu.com/p/c6222dbf157d)
        evt.stop();
    }
}, { priority: 'high' } );

button.focus(); // -> 'Focusing button, force argument="undefined"'
button.focus( true ); // Nothing is logged, the execution has been stopped.

上面有两个逻辑需要注意:
1.priority:'high',用于设置回调函数执行的优先级(顺序),不设置的话,默认为'normal',低于'high':

const priorities = {
    get( priority ) {
        if ( typeof priority != 'number' ) {
            return this[ priority ] || this.normal;
        } else {
            return priority;
        }
    },

    highest: 100000,
    high: 1000,
    normal: 0,
    low: -1000,
    lowest: -100000
}

2.evt.stop();会终止执行后续的回调函数,见ckeditor5/utils:emittermixin(事件监听机制)第五节fire。

相关文章

网友评论

    本文标题:ckeditor5/utils:如何设置observable

    本文链接:https://www.haomeiwen.com/subject/uvdpektx.html