- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在将 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/
请看一下我的代码。 int main () { Program* allcommand = new Program; allcommand->addCommand("add", new
因此,当我遇到调试断言时,我正在编写代码。现在我很想知道为什么这段代码不起作用: for(Model::MeshMap::iterator it = obj1->GetMeshes().begin()
这是我上一个问题的延续 Group, Sum byType then get diff using Java streams . 按照建议,我应该作为单独的线程发布,而不是更新原始线程。 因此,通过我
我正在实现一些非常适合 map 的代码。但是,我要迭代的列表中有大量对象,所以我的问题是哪种方法是解决此问题的最佳方法: var stuff = $.map(listOfMyObjects, some
我正在尝试创建一个包含不同类的成员函数指针的映射。成员函数都具有相同的签名。为了做到这一点,我所有的类都继承了一个 Object 类,它只有默认构造函数、虚拟析构函数和一个虚拟 ToString()
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: how do you make a heterogeneous boost::map? 有可能在 C++ 中
我有一个 Mysql 查询,请检查以下内容: SELECT `tbl_classSubjects`.`classID` , `tbl_classSubjects`.`sectionID` , `tbl
抱歉,这可能是一个基本问题。 JNA直接映射和接口(interface)映射有什么区别? 我的解释是否正确: 直接映射 : 直接使用库对象(如 Java 中的静态 main) 接口(interface
在 Twitter's Scala school collections section ,它们显示了一个带有偏函数作为值的 Map: // timesTwo() was defined earlie
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .
据我了解,从 scala stdlib 声明一个映射并没有将其专门用于原始类型。我要的不是付出装箱/拆箱的代价,而是同时拥有scala map 的接口(interface)。一个明显的选择是使用 tr
如何为这样的 JSON 响应创建对象映射,它只是一个整数数组: [ 565195, 565309, 565261, 565515, 565292, 565281, 566346, 5
是否可以为 DTO 对象创建映射然后查询它们 而不是域?如果不解释为什么? 如果我需要几个 dtos 怎么办? DTos 是只读的 ID 由 NH 自动生成 将来这些 dtos 将设置映射到链接的 d
我有一个返回的函数(常规代码) [words: "one two", row: 23, col: 45] 在 Scala 中,我将上面更改为 Scala Map,但随后我被迫将其声明为 Map[Str
我有一组与 Vanilla 磅蛋糕烘焙相关的数据(200 行),具有 27 个特征,如下所示。标签caketaste是衡量烤蛋糕的好坏程度,由 bad(0) 定义, neutral(1) , good
我有试图映射到新代码的遗留代码。 OLD_PERSON pid sid name age NEW_PERSON pid sid fid age RESOLVE_PERSON pid fid statu
我有一个表,其中一个字段可以指向其他 3 个表之一中的外键,具体取决于鉴别器值是什么(Project、TimeKeep 或 CostCenter。通常这是用子类实现的,我想知道我有什么 注意子类名称与
我有一个类型 [ST s (Int, [Int])] 的绑定(bind)我正在尝试申请runST使用映射到每个元素,如下所示: name :: [ST s (Int, [Int])] --Of Cou
在我正在进行的项目中,我有以下实体:分析师、客户 和承包商。每个都继承自基类 User。 public abstract class User { public virtual int Id
我想知道是否可以在 Vim 中创建一个映射(对于普通模式),允许用户在映射执行之前输入。 我想为我最常用的 grep 命令创建一个快捷方式的映射。我希望命令允许输入我正在搜索的内容,然后在输入时执行。
我是一名优秀的程序员,十分优秀!