敲除更新viewmodel上属性中的可观察集合



我正在使用knockout为项目创建一个基本的AJAX购物车,当视图模型上的属性更新时,视图模型内可观察集合中包含的单个产品的成本需要更新。我已经尝试了很多小时的各种解决方案,我希望有人能给我指明正确的方向。我有一把小提琴。

http://jsfiddle.net/g8BLj/3/

var product = function (title, operationName, description, parent) {
this.title = title;
this.operationName = operationName;
this.description = description;
this.cost = 9;
this.count = ko.observable(parent.recordCount);
this.subtotal = ko.computed(function () {
return this.count * this.cost;
}).bind(this);
};
order = function () {
var listName = ko.observable("not defined"),
listId = ko.observable("not defined"),
recordCount = ko.observable("not defined"),
products = [
new product('Product1', 'EMAIL_VER_DELIVERABLE', 'Description.', this),
new product('Product2', 'EMAIL_BASIC_NO_SUPRESSION_W_VERIFICATION', 'Description.', this),
new product('Product3', 'PHONE_PREM', 'Description.', this)],
total = function () {
var total = 0;
$.each(this.products(), function () {
total += this.subtotal();
});
return total;
};
// anything in the return block is considered public, anything above is private
return {
listName: listName,
listId: listId,
recordCount: recordCount,
products: products,
total: total
};
}();
ko.applyBindings(order);
// when this value changes the product Cost needs to be updated
order.listName('test list')
order.listId(1)
order.recordCount(100)

谢谢,Chris

"this"作用域有几个问题正在引发问题。

this.subtotal = ko.computed(function () {
return this.count * this.cost;
}).bind(this);

更正环境this作用域的正确方法是将"this"作为第二个参数传递到ko.computed中。此外,计数是一个可观察的,你需要评估它

this.subtotal = ko.computed(function () {
return this.count() * this.cost;
}, this);

products变量正在将"this"传递到product的构造函数中。此时的环境this是窗口,就像您正在使用匿名函数/揭示模块模式一样。

所以当

this.count = ko.observable(parent.recordCount);

计算,父项是窗口,因此recordCount==未定义。

如果你想继续使用揭示模块模式,你需要用tweek命令函数来声明你的返回对象("obj"),然后创建产品。

你也应该声明总属性为ko.computed。我使用了map/reduce而不是$.each,但这是个人偏好。

完成此操作后,它将揭示产品类的count属性的进一步问题。parent.recordCount是一个可观测值,因此您创建的可观测值是可观测值而不是可观测值。只需将可观测值分配给计数属性即可。


var product = function (title, operationName, description, parent) {
this.title = title;
this.operationName = operationName;
this.description = description;
this.cost = 9;
this.count = parent.recordCount;
this.subtotal = ko.computed(function () {
return this.count() * this.cost;
}, this);
};
order = function () {
var
listName = ko.observable("not defined"),
listId = ko.observable("not defined"),
recordCount = ko.observable("not defined"),
products = [];
var obj = {
listName: listName,
listId: listId,
recordCount: recordCount,
products: products
}
// now we have an object to push into the product class
products.push(
new product('Product1', 'EMAIL_VER_DELIVERABLE', 'Description.', obj),
new product('Product2', 'EMAIL_BASIC_NO_SUPRESSION_W_VERIFICATION', 'Description.', obj),
new product('Product3', 'PHONE_PREM', 'Description.', obj)
);
obj.total = ko.computed( function() {
return this.products
.map(function(item) { return item.subtotal(); })
.reduce( function(runningTotal, subtotal) { return runningTotal + subtotal;
}, 0);
}, obj);
// anything in the return block is considered public, anything above is private
return obj;
}();
ko.applyBindings(order);
// when this value changes the product Cost needs to be updated
order.listId(1);
order.listName('test list');
order.recordCount(100);

我认为,解决这个问题最重要的是使用对order.recordCount更改的订阅,而不是将order作为参数发送给product
你可以写这样的东西:

recordCount.subscribe(function (newValue) {
ko.utils.arrayForEach(products, function (product) {
product.count(newValue);
})
});

此外,您应该更改product.subtotal计算:

this.subtotal = ko.computed(function () {
return this.count() * this.cost;
}, this);

最新更新