65.9K
CodeProject 正在变化。 阅读更多。
Home

Ext JS MVVM技巧:第二部分。ViewModel隔离

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2017年3月27日

CPOL

2分钟阅读

viewsIcon

13788

完成第一部分并实现ViewModel隔离

引言

第一部分中,我们已经更进一步地实现了组件的封装。我们解决了外部绑定问题,并使内部绑定成为可能。 在本部分中,我们将解决在层次结构中可能发生的ViewModel数据字段名称冲突问题。

名称冲突

假设我们正在创建两个组件,一个外部组件和一个内部组件。我们不想暴露组件的内部细节,因此希望使用配置来操作其状态。在这种情况下,每个组件都有一个非唯一的color配置。

为了使实验更清晰,我们不会使用第一部分中的修复方案。我们更改了处理程序中的ViewModel。外部组件的color绑定到文本字段、标签以及内部组件的color配置。

Ext.define('Fiddle.view.OuterContainer', {
    // ...

    viewModel: {
        data: {
            color: null
        }
    },

    config: {
        color: null
    },

    items: [{
        xtype: 'textfield',
        fieldLabel: 'Enter color',
        bind: '{color}',
        listeners: {
            change: 'colorField_change'
        }
    }, {
        xtype: 'displayfield',
        fieldLabel: 'Color',
        bind: '{color}'
    }, {
        xtype: 'innercontainer',
        bind: {
            color: '{color}' // <<-- non-unique
        }
    }],

    colorField_change: function (field, value) {
        this.setColor(value);
    },

    updateColor: function (color) {
        this.getViewModel().set('color', color);
    }
});
Ext.define('Fiddle.view.InnerContainer', {
    // ...

    viewModel: {
        data: {
            color: null
        }
    },

    config: {
        color: null
    },

    items: [{
        xtype: 'textfield',
        fieldLabel: 'Color',
        bind: '{color}'
    }],

    updateColor: function (color) {
        this.getViewModel().set('color', color);
    }
});

如果我们尝试这样做,会发现绑定无法正常工作。原因是两个ViewModel都包含color数据字段。为了避免这个问题,我们应该对它们进行唯一命名。但这是否方便?这是否能保证唯一性?

扩展

因此,创建了SplitViewModel扩展。它为ViewModel的数据字段提供唯一的内部名称。结果是,ViewModel之间永远不会相互干扰。为了完成我们的示例,我们将创建一个显式的反向引用绑定,如下所示

Ext.define('Fiddle.view.OuterContainer', {
    // ...
    
    viewModel: {
        name: 'outercontainer',
        data: {
            color: null
        }
    },
    
    // ...

    items: [{
        xtype: 'innercontainer',
        bind: {
            color: '{outercontainer|color}'
        }
    }]

    // ...
});

这里发生了什么变化?

我们为外部ViewModel指定了一个name,因为它是在同一个文件中定义的匿名ViewModel。无论如何,name都会自动从alias中获取。

我们使用name|字符,为外部ViewModel指定了一个显式的反向引用:'{outercontainer|color}'

结果

ViewModel现在彼此隔离。我们可以使用ViewControllerViewModel创建独立的视图,而无需担心ViewModel之间的干扰。有了这个扩展,绑定变得非常可预测。

限制

如果您有嵌套的视图,都带有ViewModel,就像上面的示例一样,那么您必须在必要时为您的绑定添加显式的反向引用。即使属性名称是唯一的。您所需要做的就是添加ViewModelnametype,然后在属性名称前加上|字符。

Using the Code

在GitHub上找到扩展

并导入它

Ext.application({
    requires: [
        'Ext.vmx.app.SplitViewModel'
    ]
});

组合扩展

我发现当同时使用这两个扩展时,结果令人印象深刻(第一部分)。请查看此示例

没有单个处理程序。一切都通过声明式语法完成。组件的状态由配置属性控制,但内部细节通过ViewModel绑定。我希望Sencha默认情况下就这样做。

© . All rights reserved.