将自定义组件存储配置绑定到ViewModel存储

时间:2016-07-22 14:43:23

标签: javascript extjs data-binding extjs6

我在Ext JS中编写一个自定义组件,需要将商店作为其配置的一部分。我想将这个商店保留在组件的ViewModel中,我也希望它可以绑定。目前我的代码如下:

Ext.define('CustomComponent', {
    extend: 'Ext.container.Container',
    xtype: 'customcomponent',
    viewModel: {
        type: 'customcomponent'
    },
    config: {
        store: 'ext-empty-store'
    },
    initComponent: function() {
        var store = Ext.getStore(this.getConfig('store'));
        this.lookupViewModel().set('myStore', store);
        this.callParent(arguments);
    }
});

Ext.define('CustomComponentViewModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.customcomponent',
    data: {
        myStore: null
    }
});

由于多种原因,这并不理想:

  • store配置选项不可绑定。
  • 商店包含在ViewModel的data中,而不是stores。这意味着无法通过ViewModel的getStore方法访问它。

为了使商店可绑定,我可以编写如下代码:

Ext.define('CustomComponent', {
    extend: 'Ext.container.Container',
    xtype: 'customcomponent',
    viewModel: {
        type: 'customcomponent'
    },
    config: {
        store: 'ext-empty-store'
    },
    publishes: 'store'
});

Ext.define('CustomComponentViewModel', {
    extend: 'Ext.app.ViewModel',
    alias: 'viewmodel.customcomponent',
    data: {
        store: null
    },
    formulas: {
        myStore: function(get) {
            return Ext.getStore(get('store'));
        }
    }
});

但这也不理想:

  • ViewModel受到store配置的污染,该配置不一定是Ext.data.Store。它可以是商店的ID或配置对象。从本质上讲,它是一个实现细节,我想让它远离ViewModel,它将被每个子组件继承。
  • 商店仍然不是ViewModel商店配置的一部分,因此无法通过getStore访问

基本上,我正在寻找一种方法来设置我的View和ViewModel(以及ViewController,如果它有帮助),这样我就可以满足这三个标准:

  • 视图上的store配置是可绑定的。
  • store配置选项未保存在ViewModel中,或以某种方式阻止污染组件子项的ViewModel。
  • ViewModel中的商店可通过getStore
  • 访问

是否有可能同时满足所有这三个标准?如果没有,将可绑定存储配置转换为ViewModel存储的最规范方法是什么? Ext JS源代码不使用View-ViewModel架构来定义组件,所以我不能只看他们做什么。

2 个答案:

答案 0 :(得分:0)

我相信你可以像这样使用商店。

new CountDownTimer(5000,1000) {

         @Override
         public void onFinish() {
            new loginAccess().execute();

            //===========================================================
            //Move the following 3 lines to OnPostExecute
            //===========================================================
            Intent intent = new Intent(getBaseContext(), MainActivity.class);
            startActivity(intent);
            finish();

        }
        @Override
        public void onTick(long millisUntilFinished) {

        }
    }.start();

答案 1 :(得分:0)

在更彻底地阅读Ext JS 6.0.2源代码之后,我得出的结论是,如果没有覆盖或子类化Ext.app.ViewModel,就无法满足我想要的所有三个条件。我将逐一审查标准,然后讨论我认为目前最好的做法。

标准

store配置必须是可绑定的

这实际上是默认完成的;所有配置选项都是可绑定的。当我说商店必须是可绑定的时我的意思是“绑定到store配置将更新我的ViewModel中的商店”。如果store选项设置正确,publishes配置的值将发送到ViewModel,即publishes: 'store'。这会将store配置的原始值作为store发送回ViewModel,但这不是我们想要的。我认为最简单的方法是通过为每个配置选项提供的applyConfigName模板方法。这是一个例子:

Ext.define('CustomComponent', {
    extend: 'Ext.container.Container',
    xtype: 'customcomponent',
    viewModel: {
        type: 'customcomponent'
    },
    config: {
        store: 'ext-empty-store'
    },
    publishes: 'store',
    applyStore: function(store) {
        return Ext.getStore(store);
    }
});

applyStore函数在设置之前将应用于store的值,将其从商店ID或配置对象转换为实际商店。这带来了第二个标准:

store配置选项未保存在ViewModel

通过使用applyStore模板方法,我们可以将商店配置选项保留在ViewModel之外。 (实际上,它甚至使它远离我们的View!)而是发布到我们的ViewModel的store的值是它定义的实际存储。但遗憾的是,发布配置值会将它们添加到ViewModel的数据对象,而不是store对象。这将我们带到最终标准:

ViewModel中的商店可通过getStore

访问

这个标准目前无法满足。原因有两方面:

getStore仅检索通过stores配置选项

添加的商店

在Ext JS 6.0.2中,getStore通过在storeInfo Ext.app.ViewModel私有属性中查找商店来检索商店。 storeInfo属性本身是通过setupStore私有方法设置的,该方法仅在stores配置的每个成员上调用。

stores配置选项仅允许配置对象

store的{​​{1}}配置不同,Ext.grid.Panel的{​​{1}}配置选项仅允许每个商店的值为配置对象;不允许存储ID和实际商店。直接将值设置为绑定似乎有效,例如:

stores

但实际上,Ext.app.ViewModel是一个新的Ext.define('CustomComponentViewModel', { extend: 'Ext.app.ViewModel', alias: 'viewmodel.customcomponent', data: { dataStore: null }, stores: { storeStore: '{dataStore}' } }); ,配置了storeStore。这意味着在Ext.data.ChainedStore上设置过滤器和排序器不会影响source: dataStore,这可能不是您想要的。

这两个限制的组合意味着无法在ViewModel中设置商店,可以使用storeStore检索商店。

那我该怎么办?

我认为,通过可用选项,最佳做法是放弃使用dataStore检索商店的功能。虽然这是一个恼人的不一致,但它不太可能像允许隐式getStore那样导致细微的错误。这给了我们最终的代码:

getStore