我正在使用knockout为项目创建基本的AJAX购物车,并且当视图模型中的属性更新时,视图模型中的可观察集合中包含的各个产品的成本需要更新。我已经尝试了很多个小时的各种解决方案,我希望有人可以指出我正确的方向。我已经包括了一个jsfiddle。
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)
谢谢, 克里斯
答案 0 :(得分:0)
我认为,解决此问题最重要的是使用订阅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);
答案 1 :(得分:0)
“this”范围存在一些问题,导致问题。
this.subtotal = ko.computed(function () {
return this.count * this.cost;
}).bind(this);
使环境此范围正确的正确方法是将“this”作为第二个参数传递给ko.computed。此外,count是一个可观察的,你需要评估它。
this.subtotal = ko.computed(function () {
return this.count() * this.cost;
}, this);
products变量将“this”传递给产品的构造函数。此时的环境此是窗口,您使用的是匿名函数/显示模块模式。
所以当
this.count = ko.observable(parent.recordCount);
计算,父是窗口,所以recordCount == undefined。
如果你想继续使用揭示模块模式,你需要调整order函数来声明你的返回对象(“obj”),然后创建产品。
您还应该将总属性声明为ko.computed。我使用map / reduce而不是$ .each,但这是个人偏好。
完成此操作后,它会显示产品类上count属性的其他问题。 parent.recordCount是一个可观察的,因此您创建一个observable,其值是可观察的,而不是observable的值。只需将observable指定给count属性即可。
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);