ckeditor5/core:context宝磨、plugincollection和Collection

Provides a common, higher-level environment for solutions that use multiple Editor editors
or plugins that work outside the editor. Use it instead of Editor.create Editor.create()
in advanced application integrations.

Config

ckeditor5-utils下Config是一種類似于lodash get效果的類,可以通過get(obj, 'a.b.c')set(obj, 'a.b.c', 123)來獲取或設(shè)置對象obj={a : { b: {c: 1}}}翰舌,用來封裝或操作配置嚣潜。如:

let config = new Config( {
    creator: 'inline',
    language: 'pl',
    resize: {
        minHeight: 300,
        maxHeight: 800,
        icon: {
            path: 'xyz'
        }
    },
    toolbar: 'top',
    options: {
        foo: [
            { bar: 'b' },
            { bar: 'a' },
            { bar: 'z' }
        ]
    }
// 
expect( config.get( 'creator' ) ).to.equal( 'inline' );
config.set( {
    option1: 1,
    option2: {
        subOption21: 21
    }
} );
expect( config.get( 'option1' ) ).to.equal( 1 );
expect( config.get( 'option2.subOption21' ) ).to.equal( 21 );

Context

Provides a common, higher-level environment for solutions that use multiple editors or plugins that work outside the editor.
All configuration options passed to a context will be used as default options for editor instances initialized in that context.
Context plugins passed to a context instance will be shared among all editor instances initialized in this context. These will be the same plugin instances for all the editors.

  • 例1
// Creates and initializes a new context instance.
        const commonConfig = { ... }; // Configuration for all the plugins and editors.
        const editorPlugins = [ ... ]; // Regular plugins here.
        Context
            .create( {
                // Only context plugins here.
                plugins: [ ... ],
                // Configure the language for all the editors (it cannot be overwritten).
                language: { ... },
                // Configuration for context plugins.
                comments: { ... },
                ...
                // Default configuration for editor plugins.
                toolbar: { ... },
                image: { ... },
                ...
            } )
            .then( context => {
                const promises = [];
                promises.push( ClassicEditor.create(
                    document.getElementById( 'editor1' ),
                    {
                        editorPlugins,
                        context
                    }
                ) );
                promises.push( ClassicEditor.create(
                    document.getElementById( 'editor2' ),
                    {
                        editorPlugins,
                        context,
                        toolbar: { ... } // You can overwrite the configuration of the context.
                    }
                ) );
                return Promise.all( promises );
            } );
  • 例2,通過builtinPlugins設(shè)置內(nèi)置插件
// An array of plugins built into the `Context` class.
// It is used in CKEditor 5 builds featuring `Context` to provide a list of context plugins which are later automatically initialized during the context initialization.
// They will be automatically initialized by `Context` unless `config.plugins` is passed.
        // Build some context plugins into the Context class first.
        Context.builtinPlugins = [ FooPlugin, BarPlugin ];
        // Normally, you need to define config.plugins, but since Context.builtinPlugins was
        // defined, now you can call create() without any configuration.
        Context
            .create()
            .then( context => {
                context.plugins.get( FooPlugin ); // -> An instance of the Foo plugin.
                context.plugins.get( BarPlugin ); // -> An instance of the Bar plugin.
            } );
  • 例3椅贱,通過defaultConfig設(shè)置默認(rèn)配置
Context.defaultConfig = {
    foo: 1,
    bar: 2
};
Context
    .create()
    .then( context => {
        context.config.get( 'foo' ); // -> 1
        context.config.get( 'bar' ); // -> 2
    } );
// The default options can be overridden by the configuration passed to create().
Context
    .create( { bar: 3 } )
    .then( context => {
        context.config.get( 'foo' ); // -> 1
        context.config.get( 'bar' ); // -> 3
    } );

new Context(config)實例化過程

  • 通過傳參configdefaultConfig(參見例3)給Config類生成實例賦給this.config
  • plugins為key懂算,builtinPlugins(參見例2)為value只冻,更新this.config
  • this.plugins = new PluginCollection( this, availablePlugins );,PluginCollection實例化過程如下:
    PluginCollection實例化過程
  • 通過Locale生成對象賦給this.locale(詳見ckeditor5/locale:國際化方案):
this.locale = new Locale( {
            uiLanguage: typeof languageConfig === 'string' ? languageConfig : languageConfig.ui,
            contentLanguage: this.config.get( 'language.content' )
} );
this.t = this.locale.t;
  • this.editors = new Collection();计技,Collection用于對editor實例進(jìn)行諸如新增喜德、刪除和查找等管理工作。
    基本使用示例
const collection = new Collection( [ { id: 'John' }, { id: 'Mike' } ] );
console.log( collection.get( 0 ) ); // -> { id: 'John' }
console.log( collection.get( 1 ) ); // -> { id: 'Mike' }
console.log( collection.get( 'Mike' ) ); // -> { id: 'Mike' }
// Or 
const collection = new Collection();
collection.add( { id: 'John' } );
console.log( collection.get( 0 ) ); // -> { id: 'John' }
// Or  you can always pass a configuration object as the last argument of the constructor:
const emptyCollection = new Collection( { idProperty: 'name' } );
emptyCollection.add( { name: 'John' } );
console.log( collection.get( 'John' ) ); // -> { name: 'John' }
const nonEmptyCollection = new Collection( [ { name: 'John' } ], { idProperty: 'name' } );
nonEmptyCollection.add( { name: 'George' } );
console.log( collection.get( 'George' ) ); // -> { name: 'George' }
console.log( collection.get( 'John' ) ); // -> { name: 'John' }

bindTo垮媒、as和using

// Binds and synchronizes the collection with another one.
// The binding can be a simple factory:
        class FactoryClass {
            constructor( data ) {
                this.label = data.label;
            }
        }
        const source = new Collection( { idProperty: 'label' } );
        const target = new Collection();
        target.bindTo( source ).as( FactoryClass );
        source.add( { label: 'foo' } );
        source.add( { label: 'bar' } );
        console.log( target.length ); // 2
        console.log( target.get( 1 ).label ); // 'bar'
        source.remove( 0 );
        console.log( target.length ); // 1
        console.log( target.get( 0 ).label ); // 'bar'
// or the factory driven by a custom callback:
        class FooClass {
            constructor( data ) {
                this.label = data.label;
            }
        }
        class BarClass {
            constructor( data ) {
                this.label = data.label;
            }
        }
        const source = new Collection( { idProperty: 'label' } );
        const target = new Collection();
        target.bindTo( source ).using( ( item ) => {
            if ( item.label == 'foo' ) {
                return new FooClass( item );
            } else {
                return new BarClass( item );
            }
        } );
        source.add( { label: 'foo' } );
        source.add( { label: 'bar' } );
        console.log( target.length ); // 2
        console.log( target.get( 0 ) instanceof FooClass ); // true
        console.log( target.get( 1 ) instanceof BarClass ); // true
// or the factory out of property name:
        const source = new Collection( { idProperty: 'label' } );
        const target = new Collection();
        target.bindTo( source ).using( 'label' );
        source.add( { label: { value: 'foo' } } );
        source.add( { label: { value: 'bar' } } );
        console.log( target.length ); // 2
        console.log( target.get( 0 ).value ); // 'foo'
        console.log( target.get( 1 ).value ); // 'bar'
// It's possible to skip specified items by returning falsy value:
        const source = new Collection();
        const target = new Collection();
        target.bindTo( source ).using( item => {
            if ( item.hidden ) {
                return null;
            }
            return item;
        } );
        source.add( { hidden: true } );
        source.add( { hidden: false } );
        console.log( source.length ); // 2
        console.log( target.length ); // 1
  • this._contextOwner初始化為null舍悯,在_addEditor方法中會對其賦值:
/*
Reference to the editor which created the context.
Null when the context was created outside of the editor.
It is used to destroy the context when removing the editor that has created the context.
*/
this._contextOwner = null;

editor.js中,會調(diào)用Context方法和_addEditor

class Editor {
   constructor(config = {}) {
    this._context = config.context || new Context( { language: config.language } );
    this._context._addEditor( this, !config.context );
  }
}
  • _addEditor
// Adds a reference to the editor which is used with this context.
// This method should only be used by the editor.
_addEditor( editor, isContextOwner ) {
    if ( this._contextOwner ) {
        /**
         * Cannot add multiple editors to the context which is created by the editor.
         *
         * @error context-addeditor-private-context
         */
        throw new CKEditorError( 'context-addeditor-private-context' );
    }
    this.editors.add( editor );
    if ( isContextOwner ) {
        this._contextOwner = editor;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睡雇,一起剝皮案震驚了整個濱河市萌衬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌它抱,老刑警劉巖秕豫,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抗愁,居然都是意外死亡馁蒂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門蜘腌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沫屡,“玉大人,你說我怎么就攤上這事撮珠【诓保” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵芯急,是天一觀的道長勺届。 經(jīng)常有香客問我,道長娶耍,這世上最難降的妖魔是什么免姿? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮榕酒,結(jié)果婚禮上胚膊,老公的妹妹穿的比我還像新娘。我一直安慰自己想鹰,他們只是感情好紊婉,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辑舷,像睡著了一般喻犁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天肢础,我揣著相機(jī)與錄音还栓,去河邊找鬼。 笑死传轰,一個胖子當(dāng)著我的面吹牛蝙云,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播路召,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼波材!你這毒婦竟也來了股淡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤廷区,失蹤者是張志新(化名)和其女友劉穎唯灵,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體隙轻,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡埠帕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玖绿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敛瓷。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖斑匪,靈堂內(nèi)的尸體忽然破棺而出呐籽,到底是詐尸還是另有隱情,我是刑警寧澤蚀瘸,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布狡蝶,位于F島的核電站,受9級特大地震影響贮勃,放射性物質(zhì)發(fā)生泄漏贪惹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一寂嘉、第九天 我趴在偏房一處隱蔽的房頂上張望奏瞬。 院中可真熱鬧,春花似錦垫释、人聲如沸丝格。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽显蝌。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曼尊,已是汗流浹背酬诀。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留骆撇,地道東北人瞒御。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像神郊,于是被迫代替她去往敵國和親肴裙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348