深入ViewModel-ViewModel Internals

我们已经了解了 ViewModel 能做什么,我们再来深入了解一下 ViewModel 内部的机制,有助于问题的跟踪和诊断。

ViewModel 主要负责两个工作:管理对数据对象的变更,当数据变更时安排计划绑定。

ViewModel Data and Inheritance

ViewModel 类管理一个“数据”对象,利用 JavaScript 的原型链(prototype chain)实现继承。如下图所示:

这说明,所有的组件都可以读取上层容器(top-level container)设置的属性(存储在上层容器的数据对象,Data 1)。假设 Container 1 的 ViewModel 如下:

viewModel: {
    data: {
        foo: 42
    }
}

这允许所有的组件绑定到 {foo}。这种方式常用于跟踪应用程序的任何层次都需要访问的重要记录(例如:当前登录用户)。事实上,由于使用 JavaScript 的原型链提供数据,当数据变更后,如果需要共享变更的属性,可以在 ViewModel 中发布(publish)一个对象。在子容器 Container 2 中考虑使用一个双向绑定到 {foo}:

{
    xtype: 'textfield',
    bind: '{foo}'
}

这个文本框通过 Data 2 的原型链从 Data 1 获取到 foo 属性的值 42。如果该组件修改了内容,这个值是存储在 Data 2 上的。这是因为组件是绑定到 ViewModel 上的,双向绑定在 ViewModel 2 上生效,像普通的 JavaScript 对象一样,设置 Data 2foo 属性。。这种模式也可以用于初始化一些值,然后从视图中分离出来。

为了要实时共享继承的属性,应该使用存储在根 ViewModel 上的对象:

viewModel: {
    data: {
        stuff: {
            foo: 42
        }
    }
}

现在,双向绑定将更新共享的 stuff 对象的 foo 属性:

{
    xtype: 'textfield',
    bind: '{stuff.foo}'
}

计划和依赖-Scheduling and Dependencies

加快数据绑定处理的关键是避免冗余和不必要的计算。

为了管理这些事项, ViewModel 跟踪数据间的依赖关系。每个绑定和公式都有一个依赖。ViewModel 将这些依赖关系分解为间接的关系,同时建立一个线性的计划,当数据变化时,这个计划将被延期进行处理。

所以,当你设置或修改 ViewModel 数据的值或数据记录的属性时,不必担心立即发生大量的重新计算。同样,如果有 7 个公式,每个公式使用另一个公式(所以有 7 层的深度链),每个公式又依赖其他 7 个值,变更这 49 个值,每个公式只会被重新计算一次。

为了达到这个目的,这些依赖项必须能够被 ViewModel 所识别,并且必须是非循环引用的。循环引用将引发错误。例如:

Ext.define('App.view.broken.BrokenModel', {
    extend: 'Ext.app.ViewModel',

    formulas: {
        bar: function (get) {
            return get('foo') / 2;
        },
        foo: function (get) {
            return get('bar') * 2;
        }
    }
});

在实际的应用程序中,这样的 bug 可能不是特别明显,但是很显然, foobar 相互依赖,无法确定计算顺序以得到一个正确的结果。

公式依赖-Formula Dependencies

当一个公式使用一个明确的绑定,那么它的依赖关系是明显的。当一个公式只提供了一个函数或者一个 get 方法,那么 ViewModel 将分析函数的内容,搜索正确的引用关系。详细信息参见 Ext.app.bind.Formula

results matching ""

    No results matching ""