gpt4 book ai didi

javascript - 使用对象继承时 Knockout 映射的问题

转载 作者:行者123 更新时间:2023-11-30 12:22:33 25 4
gpt4 key购买 nike

在将 KO 映射插件与子类对象一起使用时,出现一些我不太了解的奇怪行为。

用例:

  • 服务器有许多用于 AJAX 的简单模型类应用程序接口(interface)。

  • 我想生成一个生成 KO observables 的 stub 类对于这些类的属性,这样如果我更改服务器代码 stub 类会自动更新为新的可观察对象property - 我需要这个,这样我就可以创建全新的对象而无需从现有数据。

  • 然后我希望能够创建 stub 的子类,例如为 UI、操作方法、客户端状态等计算这些额外的属性不需要映射回服务器——事实上它们不能是,因为服务器模型会有它们(或者它们会在 stub 中)

我在运行时遇到问题。

这里是一些简化的代码:

function ItemModelBase(data, mapping)
{
if(data)
ko.mapping.fromJS(data, mapping, this);

this.Name = this.Name || ko.observable();
}

function ItemModel(data, mapping)
{
var _this = this;

ItemModelBase.call(this, data, mapping);

this.Salutation = ko.computed(function() { return 'Hello ' + _this.Name(); });
}

// Comment this out and it works
ItemModel.prototype = new ItemModelBase;

function Model()
{
var _this = this;

var _mapping = {
'Items': {
create: function(o) { return new ItemModel(o.data); }
}
};

this.Items = ko.observableArray();

this.load = function()
{
ko.mapping.fromJS({
Items: [
{ Name: 'Aardvark' },
{ Name: 'Bat' },
{ Name: 'Cheetah' },
{ Name: 'Duiker' },
{ Name: 'Ocelot' }
]
}, _mapping, _this);
};
}

var model = new Model();
ko.applyBindings(model);
model.load();

使用 View :

<ul data-bind="foreach: Items">
<li>
<span data-bind="text: Name"></span>:
<span data-bind="text: Salutation"></span>
</li>
</ul>

这显示的是正确数量的项目列表,但仅使用最后一项的数据 - 结果:

  • 山猫:你好山猫
  • 山猫:你好山猫
  • 山猫:你好山猫
  • 山猫:你好山猫
  • 山猫:你好山猫

如果我不子类化基础对象,即我注释掉 ItemModel.prototype = new ItemModelBase; 行,它会按预期工作。

我的主要语言是 C#,我发现 Javascript 的继承很难理解;这里发生了什么?据我所知,没有原型(prototype)它就可以工作,因为基本构造函数调用只是 A.N.正在向当前实例添加大量属性的其他 JS 调用。

这适用于这种情况,但可能意味着如果我向基类原型(prototype)添加一些常用函数,我将无法使用它们?

我想我需要一个主要的单一问题,所以它是:为什么只显示最后一项,我该怎么做?

JFfiddle:https://jsfiddle.net/whelkaholism/d427mssa/

编辑:如果我包含继承然后创建一个新模型,则该新模型也具有最后一项的属性。真的不明白,但它看起来像是在为原型(prototype)而不是实例赋值?

console.log(ko.toJSON(new ItemModel()));

结果:

{"Name":"Ocelot","Salutation":"Hello Ocelot"}

编辑:Tomalak发布了一个似乎已被删除的答案,这很遗憾,虽然我仍然不知道发生了什么,但它确实给出了修复。

问题是这样的:this.Name = this.Name || ko.observable();

如果我将 observable 定义移动到映射上方,它就会起作用:

function ItemModelBase(data, mapping)
{
this.Name = ko.observable();
// Exhibits the same bug as original code
// this.Name = this.Name || ko.observable();

if(data)
ko.mapping.fromJS(data, mapping, this);
}

奇怪的是,离开条件会导致相同的错误,即使我对 JS 的理解是 this.Name 在那个时候是未定义的,导致该语句具有 `ko.observable()' 的值并且与没有 cnodition 的代码?

最佳答案

不要尝试在原型(prototype)链上游的任何位置创建计算或可观察对象。以下是您可以做什么和不能做什么:

  • 您可以修改原型(prototype)以在 View 模型之间共享通用的、不可观察的 (!) 属性和方法。

    var common = {
    baz: function () {
    return ko.unwrap(this.bar) || ko.unwrap(this.foo);
    }
    };

    function VM1() {
    this.foo = ko.observable();
    }
    VM1.prototype = common;

    function VM2() {
    this.foo = ko.observable();
    this.bar = ko.observable();
    }
    VM2.prototype = common;

    var vm2 = new VM2();
    vm2.foo("FOO");
    vm2.baz(); // -> returns "FOO";
  • 您不能(读作:不应该)在原型(prototype)链中有其他 View 模型。由于所有原型(prototype)本身都是活对象实例,因此它们的所有可观察对象都将在您的实际 viewmodel 实例之间共享。唯一有意义的情况是,如果您想在实例之间共享可订阅 (!) 数据。

    function VM0() {
    this.count = ko.observable(0);
    }
    VM0.prototype.increment = function () {
    this.count(this.count() + 1);
    };

    function VM1() {
    this.foo = ko.observable();
    this.count.subscribe(function (newCount) {
    // count has increased across all VM1 instances
    });
    }
    VM1.prototype = new VM0();

    var vm1 = new VM1();
    vm1.inc(); // -> triggers subscription across all VM1 instances
  • 您可以使用函数将通用的、独立的功能(包括可观察对象)附加到 View 模型实例。这基本上就是应用不同的构造函数,如 ItemModelBase.call(this, ...); 会做的事情。

    function VM1() {
    this.foo = ko.observable();
    }

    function VM2() {
    VM1.call(this); // creates foo observable
    this.bar = ko.observable();
    }
  • 您不能在同一 View 模型实例上多次调用 ko.mapping(即首先映射基本属性,然后映射特定属性)。映射插件将其内部状态保存在实例变量本身中——第二次运行将覆盖第一次的状态。 (当然,您仍然可以第二次映射相同属性列表,即更新它们的值。)

所有这些都为 C# 类型继承层次结构留下了非常小的空间。除非您有共同的功能要共享,否则不要费心在 JS 中构建 View 模型层次结构。

关于javascript - 使用对象继承时 Knockout 映射的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30504149/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com