Chr*_*nce 6 knockout-mapping-plugin knockout.js
我有一系列从服务中回来的物品.我正在尝试为每个Item实例定义一个计算的observable,所以我的直觉告诉我把它放在原型上.
计算的observable的一种情况:系统计算点,但用户可以选择覆盖计算的值.我需要保持计算值可用,以防用户删除覆盖.我还需要合并用户指定和计算的点,并将总计加起来.
我正在使用映射来执行以下操作:
var itemsViewModel;
var items = [
{ 'PointsCalculated' : 5.1 },
{ 'PointsCalculated' : 2.37, 'PointsFromUser' : 3 }
];
var mapping = {
'Items' : {
create : function(options) {
return new Item(options.data);
}
}
};
var Item = function(data) {
var item = this;
ko.mapping.fromJS(data, mapping, item);
};
Item.prototype.Points = function () {
var item = this;
return ko.computed(function () {
// PointsFromUser may be 0, so only ignore it if the value is undefined/null
return (item.PointsFromUser != null) ? item.PointsFromUser : item.PointsCalculated;
});
};
ko.mapping.fromJS(items, mapping, itemsViewModel);
Run Code Online (Sandbox Code Playgroud)
它现在的工作方式,我必须调用匿名函数来返回计算的observable.这似乎为每个绑定创建了一个计算的observable的新实例,这使得将它放在原型上的大部分内容都失败了.每次访问一个observable时,必须破译要使用多少个括号,这有点烦人.
它也有些脆弱.如果我尝试在代码中访问Points(),我不能这样做
var points = 0;
var p = item.Points;
if (p && typeof p === 'function') {
points += p();
}
Run Code Online (Sandbox Code Playgroud)
因为它改变了Points()到DOMWindow的上下文,而不是item.
如果我将create()中的computed放在映射中,我可以捕获上下文,但是每个对象实例上都有一个方法的副本.
我找到了Michael Best的Google网上论坛帖子(http://groups.google.com/group/knockoutjs/browse_thread/thread/8de9013fb7635b13).原型在"激活"上返回一个新的计算观察值.我还没弄明白什么叫"激活"(也许是Objs?),但是我猜它每个对象仍然会发生一次,我不知道"这个"会得到什么范围.
在这一点上,我相信我已经超越了已发布文档中的内容,但我仍在努力破译从源头上发生的事情.
您提到您不希望ko.computed
在javascript类的每个实例上都有该函数的实例,但是,这并不能真正解决ko的功能构建方式.当你使用ko.computed
或者ko.observable
他们创建特定的内存指针到私有变量时,你通常不希望在类实例之间共享(尽管在极少数情况下你可能).
我做这样的事情:
var Base = function(){
var extenders = [];
this.extend = function(extender){
extenders.push(extender);
};
this.init = function(){
var self = this; // capture the class that inherits off of the 'Base' class
ko.utils.arrayForEach(extenders, function(extender){
// call each extender with the correct context to ensure all
// inheriting classes have the same functionality added by the extender
extender.call( self );
});
};
};
var MyInheritedClass = function(){
// whatever functionality you need
this.init(); // make sure this gets called
};
// add the custom base class
MyInheritedClass.prototype = new Base();
Run Code Online (Sandbox Code Playgroud)
然后对于计算的observables(它必须是你的每个实例上的实例函数MyInheritedClass
)我只是声明它们extender
:
MyInheritedClass.prototype.extend(function(){
// custom functionality that i want for each class
this.something = ko.computed(function() {
return 'test';
});
});
Run Code Online (Sandbox Code Playgroud)
鉴于您的示例和Base
上面定义的类,您可以轻松地执行以下操作:
var Item = function(data) {
var item = this;
ko.mapping.fromJS(data, mapping, item);
this.init(); // make sure this gets called
};
Item.prototype = new Base();
Item.prototype.extend(function () {
var self = this;
this.Points = ko.computed(function () {
// PointsFromUser may be 0, so only ignore it if the value is undefined/null
return (self.PointsFromUser != null) ?
self.PointsFromUser : self.PointsCalculated;
});
};
Run Code Online (Sandbox Code Playgroud)
然后,您的Item
类的所有实例都将具有Points
属性,并且它将正确处理ko.computed
每个实例的逻辑.