当需要父视图模型时,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(例如width / height / etc)和foo配置。

所以说我然后尝试在ConcreteComponent中使用它。我知道可重用组件具有config foo,因此我应该能够将其绑定到自己的viewmodel,这就是我要做的。但是,这不起作用,它显示foo = Foo,而不是(预期的)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
        });
    }
});

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...