extjs - 当需要父视图模型时,Extjs 使用子视图模型数据
问题描述
考虑这样的片段(可以在https://fiddle.sencha.com/上运行,并且在右上角的组合框中选择经典而不是现代):
Ext.define('ReusableComponent', {
xtype: 'reusable',
extend: 'Ext.Container',
config: {
foo: 'Foo'
},
updateFoo: function(foo) {
this.getViewModel().set('foo', foo);
},
viewModel: {
data: {
foo: 'Foo'
}
},
items: [{
bind: {
html: 'foo = {foo}'
}
}]
});
Ext.define('ConcreteComponent', {
extend: 'Ext.panel.Panel',
viewModel: {
data: {
foo: 'Bar'
}
},
layout: 'fit',
items: [{
xtype: 'reusable',
bind: {
foo: '{foo}'
}
}]
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('ConcreteComponent', {
renderTo: Ext.getBody(),
title: 'ConcreteComponent',
width: 200,
height: 200
});
}
});
梦想是拥有一个可重用的组件,它具有定义的外部接口,并且知道它应该足够了。那些使用该组件的人不必知道它的内部结构。在此示例中,外部接口是从 Ext.Container 继承的通用配置(如宽度/高度/等),以及foo
config.
所以说我然后尝试在 ConcreteComponent 中使用它。我知道可重用组件有 config foo,因此我应该能够将它绑定到我自己的视图模型,这就是我所做的。但是,这不起作用,它显示foo = Foo
, 而不是 (expected) foo = Bar
。原因似乎很清楚——我在不知不觉中使用了孩子的视图模型中已经存在的名称,而 extjs 选择了它而不是我在 ConcreteComponent 中定义的名称。也很清楚如何创可贴修复此问题(例如,在 ConcreteComponent 中将 viewmodel 数据属性从 重命名foo
为foo2
)。但这迫使人们了解该可重用组件的内部结构,而不仅仅是它的公共接口。有没有办法解决这个问题?还是无论如何都应该将子视图模型视为其公共界面的一部分?
解决方案
看起来解决方案是简单地在私有属性下手动创建一个视图模型(它分解了视图模型的子父链 extjs 在组件的视图模型及其容器的视图模型https://docs.sencha.com/extjs/6.2.0/ classic/Ext.Component.html#cfg-viewModel),并通过 viewModel 配置将其显式传递给可重用组件的子组件。使用defaults
似乎工作正常。我在偶然发现颜色选择器的源代码https://docs.sencha.com/extjs/6.2.0/classic/src/Selector.js.html时看到了解决方案。这是问题的固定代码
Ext.define('ReusableComponent', {
xtype: 'reusable',
extend: 'Ext.Container',
config: {
foo: 'Foo'
},
updateFoo: function(foo) {
this.childViewModel.set('foo', foo);
},
constructor: function() {
this.childViewModel = Ext.create('Ext.app.ViewModel', {
data: {
foo: 'Foo'
}
});
this.defaults = {
viewModel: this.childViewModel
};
this.callParent(arguments);
},
items: [{
bind: {
html: 'foo = {foo}'
}
}]
});
Ext.define('ConcreteComponent', {
extend: 'Ext.panel.Panel',
viewModel: {
data: {
foo: 'Bar'
}
},
layout: 'fit',
items: [{
xtype: 'reusable',
bind: {
foo: '{foo}'
}
}]
});
Ext.application({
name : 'Fiddle',
launch : function() {
Ext.create('ConcreteComponent', {
renderTo: Ext.getBody(),
title: 'ConcreteComponent',
width: 200,
height: 200
});
}
});
推荐阅读
- spring-boot - 处理重复事件的事件提醒
- regex - Regex 表达式的匹配器为假,而表达式、模式和字符串均有效
- node.js - 无法从我网络中的另一台计算机查看我的节点 js 服务器中的数据
- angular - 在 Angular 9 中的 Mat-dialog-box 中进行更改时出现编译错误
- r - addResourcePath 未设置 www
- python - 通过元组解包分配列表返回元组,而不是列表 [Python]
- selenium-webdriver - 为什么 .//div//*[contains(text(), '${form}')] 不起作用,而是改为 .//div//*[text() = '${form}']作品
- r - 如何查找我从 R 中的网站上抓取的书名中单词的频率
- microsoft-graph-api - 使用图形 api 获取已删除的事件数据
- java - 如何在 android 应用程序上随机更改 WebView User-Agent?