使用TypeScript的Kendo UI MVVM - 将ViewModels作为“类”

时间:2014-01-20 17:50:08

标签: kendo-ui typescript

我正在将项目转换为Typescript,它使用了Kendo UI的MVVM架构。但是我对类的概念及其与视图模型的关系存在一些问题。

我将建立一个类并扩展kendo.data.ObservableObject,这是您创建视图模型的方法,并使用我的字段填充它,如下所示。

export class ViewModelSample extends kendo.data.ObservableObject {
   Id: string = null;
   Name: string = null;
   Items: kendo.data.ObservableArray = [];
   // other fields
   constructor() {
      super();
   }

   map(params){
      // some code
   }
}

基本上这个类代表我的视图模型,很好地封装了。所以我这样召唤它;

var viewModel = new ViewModelSample();
kendo.bind($('#binding-area'), viewModel);

这种方法效果很好,但行为变得有点尴尬。例如,如果我在类中有一个集合并向其推送内容,则用户界面不会更新。

如果我在普通的javascript中这样做,它可以工作;

viewModel.Items.push(new Item(/* parameters */));
// view model updates, and user interface updates

但是,如果我在打字稿中执行此操作,则视图模型会更新,但DOM不会。我必须手动输入...

viewModel.Items.trigger('change');

为了让UI更新。

任何人都可以帮助我理解为什么会这样吗?

3 个答案:

答案 0 :(得分:4)

我也遇到过这个问题,实际上是由于TypeScript生成JS的方式。

在普通的JS中,您可以这样做:

new kendo.ObservableObject({
    items: []
});

并且构造函数会自动将items[]包装到新的ObservableArray中。

然而,TypeScript中的行为失败,因为代码:

export class ViewModelSample extends kendo.data.ObservableObject {
    Items: kendo.data.ObservableArray = [];

    constructor() {
       super();
    }

实际上会生成类似的内容:

function ViewModelSample() { // constructor
    _super.call(this);       // call to ObservableObject constructor (super())
    this.Items = [];         // add Items to this.
}

因此,Items属性在调用ObservableObject构造函数之后才会添加到ViewModel中,因此Kendo不会知道它,也不会将其包装到{{1 }}

排序只是从剑道期望的普通JavaScript开始的。

@ Anzeo关于手动将项目初始化为ObservableArray的建议将主要起作用

ObservableArray

然而,ObservableArray的Items: kendo.data.ObservableArray = new kendo.data.ObservableArray([]); 将无法正确设置为ViewModel,因此有时如果您尝试将MVM绑定到绑定到parent的ListView模板内的ViewModel上的函数或属性,它将无法在ViewModel上找到属性或函数。

您可以通过在devtools控制台中执行此操作来证明:

Items

这确实是一种情况,在这种情况下,TypeScript只会阻碍它... ...


正确的解决方案是在调用x = new kendo.data.ObservableObject({ items: [] }); x.items.parent(); // returns the object 'x' (correct) y = new kendo.data.ObservableObject(); y.items = new kendo.data.ObservableArray([]); y.items.parent(); // return undefined (but should be the object 'y') 之前,在构造函数中初始分配类变量

super()

以正确的顺序生成JS:

class ViewModelSample extends ObservableObject {
    Items: kendo.data.ObservableArray;

    constructor() {
        this.Items = [];
        super();
    }
}

有趣的是,typescriptlang.org上的游乐场似乎并不关心这一行:

function ViewModelSample() {
    this.Items = [];  // Items assigned before call to ObservableObject constructor
    _super.call(this);
}

将一个数组赋给一个应该是this.Items = []; 类型的变量,但如果真正的编译器抛出错误,那么你也可以这样做

ObservableArray

这应该有效。只要生成的JS在调用this.Items = new kendo.data.ObservableArray([]); 构造函数之前将Items属性添加到对象。

答案 1 :(得分:3)

您必须在构造函数的末尾调用super.init(this)来正确设置依赖关系跟踪。根据文件:

constructor() {
    ...

    super();
    super.init(this);
}

答案 2 :(得分:2)

您需要将items属性实例化为Kendo ObservableArray。目前你只是在TypeScript中定义它的类型(我很惊讶编译器没有抱怨这个?)。

将您的代码更新为:

Items: kendo.data.ObservableArray = new kendo.data.ObservableArray([]);

有关详细信息,请参阅Kendo docs