【发布时间】:2015-05-28 22:37:34
【问题描述】:
在将 KO 映射插件与子类对象一起使用时,我不太会遇到一些奇怪的行为。
用例:
服务器有许多用于 AJAX 的简单模型类 API。
我想生成一个存根类来生成 KO observables 对于这些类的属性,因此如果我更改服务器代码 存根类会自动更新为新的 observable 属性 - 我需要这个,所以我可以创建全新的对象而无需映射 现有数据。
然后我希望能够创建一个存根的子类,例如 计算 UI、操作方法、客户端状态等。这些额外的 属性不需要映射回服务器 - 事实上它们不能 是,因为服务器模型将拥有它们(或者它们会在存根中)
我无法正常工作。
这里是一些精简的代码:
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();
使用视图:
<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 的继承非常难以理解;这里发生了什么?据我所知,没有原型它可以工作,因为基本构造函数调用只是 A.N.其他向当前实例添加属性负载的 JS 调用。
这适用于这种情况,但大概意味着如果我向基类原型添加一些常用函数,我将无法使用它们?
我想我需要一个主要的问题,所以它是:为什么只显示最后一个项目,我该怎么办?
JFfiddle:https://jsfiddle.net/whelkaholism/d427mssa/
编辑:如果我包含继承然后创建一个新模型,则该新模型也具有最后一项的属性。真的不明白,但它看起来像是在为原型而不是实例分配值?
console.log(ko.toJSON(new ItemModel()));
结果:
{"Name":"Ocelot","Salutation":"Hello Ocelot"}
编辑:Tomalak 发布了一个似乎已被删除的答案,这很遗憾,因为虽然我仍然不知道发生了什么,但它确实提供了修复。
问题是这样的:this.Name = this.Name || ko.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()' 的值并且与没有条件的代码?
【问题讨论】:
-
恐怕我没有看到该示例的相关性?问题在于无法链接构造函数本身,它是原型继承以及它导致的 Knockout 映射的特定问题。
-
目前尚不清楚您希望从原型中获得什么。通常,原型包含(仅)方法。您已使其包含 Name,这是一个属性,这意味着所有没有自己的 Name 属性的实例共享一个 Name。
-
这是一个精简的例子;无可否认,在这里分配原型是没有意义的,但在实际代码中,我可能想添加实用程序方法。但是,我认为您实际上已经确定了我的问题;我在 C# 中考虑属性访问器是可覆盖的,但是如果设置原型导致共享实际属性值,那么这绝对不是我想要的 - 我应该认为它们更像 C# 字段,我猜。