ckeditor5/utils:如何设置observable

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

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

  • 如何设置类为observable
    通过混入ObservableMixin,可以使任何类变成observable,如View基类;关于ObservableMixin,详见ckeditor5/utils:ObservableMixin。
  • set:如何设置单个属性为observable
    通过从View基类获得set得方法设置属性为observable,如buttonview。

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。

  • 更多用法见ui-library#views。
© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容