将自定义组件存储配置绑定到 ViewModel 存储
Posted
技术标签:
【中文标题】将自定义组件存储配置绑定到 ViewModel 存储【英文标题】:Bind custom component store config to ViewModel store 【发布时间】:2016-11-26 12:36:27 【问题描述】:我正在用 Ext JS 编写一个自定义组件,它需要一个存储作为其配置的一部分。我想把这个 store 保存在组件的 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。
可通过getStore
访问 ViewModel 中的商店。
是否有可能同时满足所有这三个条件?如果不是,将可绑定存储配置转换为 ViewModel 存储的最规范方法是什么? Ext JS 源码没有使用 View-ViewModel 架构来定义组件,所以我不能只看他们做了什么。
【问题讨论】:
【参考方案1】:我相信您可以像这样使用商店。
Ext.define('CustomComponentViewModel',
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.customcomponent',
formulas:
myStore: function(get)
return Ext.getStore(get('store'));
,
stores:
myStore:
fields: [
name: 'id'
,
name: 'name'
,
name: 'description'
]
,
);
Ext.define('CustomComponent',
extend: 'Ext.container.Container',
xtype: 'customcomponent',
viewModel:
type: 'customcomponent'
,
config:
bind:
store: 'myStore'
);
【讨论】:
我对你的建议有点困惑。这将如何让商店由组件设置? 我想我可能对您需要什么感到困惑。很高兴你明白了!【参考方案2】:在更彻底地阅读了 Ext JS 6.0.2 源代码之后,我得出的结论是,如果不覆盖或继承 Ext.app.ViewModel
,就不可能满足我想要的所有三个条件。我将逐一介绍标准,然后讨论我认为当前的最佳做法。
标准
store
配置必须是可绑定的
这实际上是默认完成的;所有配置选项都是可绑定的。当我说商店必须是可绑定的时,我的意思是“绑定到store
配置将更新我的 ViewModel 中的商店”。如果publishes
选项设置得当,store
配置的值将被发送到 ViewModel,即publishes: 'store'
。这会将store
配置的原始值作为store
发送回ViewModel,但这不是我们想要的。我认为解决此问题的最简洁方法是通过为每个配置选项提供的apply<em>ConfigName</em>
模板方法。这是一个例子:
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 的 store
的值是它定义的实际存储。然而不幸的是,发布配置值会将它们添加到 ViewModel 的数据对象中,而不是存储对象中。这将我们带到了最终标准:
ViewModel 中的存储可通过getStore
访问
目前无法满足此标准。原因有两个:
getStore
仅检索通过 stores
配置选项添加的商店
在 Ext JS 6.0.2 中,getStore
通过在 Ext.app.ViewModel
的 storeInfo
私有属性中查找存储来检索它们。 storeInfo
属性本身是通过 setupStore
私有方法设置的,该方法仅在 stores
配置的每个成员上调用。
stores
配置选项只允许配置对象
与Ext.grid.Panel
的store
config 不同,Ext.app.ViewModel
的stores
config 选项只允许每个store 的值是config 对象;不允许使用商店 ID 和实际商店。直接将值设置为绑定似乎可行,例如:
Ext.define('CustomComponentViewModel',
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.customcomponent',
data:
dataStore: null
,
stores:
storeStore: 'dataStore'
);
但实际上,storeStore
是一个新的Ext.data.ChainedStore
,它配置了source: dataStore
。这意味着在storeStore
上设置过滤器和排序器不会影响dataStore
,这可能不是我们想要的。
这两个限制的组合意味着不可能在 ViewModel 中设置可以使用getStore
检索的存储。
那我该怎么办?
我认为在可用选项的情况下,最好的做法是放弃使用getStore
检索商店的能力。虽然这是一个令人讨厌的不一致,但它不太可能像允许隐式 ChainedStore
那样导致细微的错误。这给了我们最终的代码:
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);
);
Ext.define('CustomComponentViewModel',
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.customcomponent',
data:
store: null
);
【讨论】:
以上是关于将自定义组件存储配置绑定到 ViewModel 存储的主要内容,如果未能解决你的问题,请参考以下文章