Kendo UI MVVM 与 TypeScript - 将 ViewModel 制作为“类”

2024-03-11

我正在将一个项目转换为 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更新。

谁能帮助我理解为什么会发生这种情况?


我也遇到过这个问题,这实际上是由于 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.
}

So the Items属性不会添加到 ViewModel 直到之后ObservableObject构造函数被调用,所以 Kendo 不知道它,并且不会将其包装到ObservableArray.

该顺序与 Kendo 对正常 JavaScript 的期望正好相反。

@Anzeo 建议手动将项目初始化为ObservableArray大部分都会起作用

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

然而 ObservableArray 的parent不会正确设置为 ViewModel,因此有时如果您尝试 MVVM 在 ListView 模板内的 ViewModel 上绑定一个函数或属性,该模板会绑定到Items,它将无法找到 ViewModel 上的属性或函数。

您可以通过在开发工具控制台中执行此操作来证明这一点:

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')

这实际上是 TypeScript 带来的阻碍多于它的帮助......


正确的解决方案是对类变量进行初始赋值inside你的构造函数,在调用之前super().

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

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

它以正确的顺序生成 JS:

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

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

this.Items = [];

将数组分配给应该类型的变量ObservableArray,但是如果真正的编译器抛出错误,那么你也可以这样做

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

那应该有效。生成的JS只要添加Items之前的对象的属性ObservableObject构造函数被调用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kendo UI MVVM 与 TypeScript - 将 ViewModel 制作为“类” 的相关文章

随机推荐