我正在学习knockout.js。因此,我尝试构建一个样本购物车,最初下拉产品数据会随附。当用户选择任何产品时,相应的价格和数量将填入右输入控件,子总数将由计算属性自动计算。
最初,当我运行我的程序时,一个数据显示为购物车,但是当我选择任何产品时,价格和数量值没有被填满,并且没有显示子总数。我是KO的新人,为什么我犯了一些愚蠢的错误,在我眼前并没有明白。所以请指导我在哪里弄错了。
<table id="table1" cellspacing="0" cellpadding="0" border="0">
<tr>
<th style="width:150px">Product</th>
<th>Price ($)</th>
<th>Quantity</th>
<th>Amount ($)</th>
</tr>
<tbody data-bind='template: {name: "orderTemplate", foreach: lines}'></tbody>
</table>
<script type="text/html" id="orderTemplate">
<tr>
<td><select data-bind="options: products,
optionsText: 'name',
value: id,
optionsCaption:'--Select--'">,
value: $parent.product
</select>
</td>
<td><span data-bind="value: price" /></td>
<td><input data-bind="value: quantity" /></td>
<td><span data-bind="value: subtotal" /></td>
</tr>
</script>
<script type="text/javascript">
var _products = [
{
"name": "1948 Porsche 356-A Roadster",
"price": 53.9
, quantity: 1
},
{
"name": "1948 Porsche Type 356 Roadster",
"price": 62.16
, quantity: 1
},
{
"name": "1949 Jaguar XK 120",
"price": 47.25
, quantity: 1
},
{
"name": "1952 Alpine Renault 1300",
"price": 98.58
, quantity: 1
},
{
"name": "1952 Citroen-15CV",
"price": 72.82
, quantity: 1
},
{
"name": "1956 Porsche 356A Coupe",
"price": 98.3
, quantity: 1
},
{
"name": "1957 Corvette Convertible",
"price": 69.93
, quantity: 1
}];
function formatCurrency(value) {
return "$" + value.toFixed(2);
}
var CartLine = function () {
var self = this;
self.products = ko.observableArray(_products);
self.product = ko.observable();
self.quantity = ko.observable(1);
self.price = ko.observable(1);
self.subtotal = ko.computed(function () {
return self.product() ? self.product().price * parseInt("0" + self.quantity(), 10) : 0;
});
};
var Cart = function () {
// Stores an array of lines, and from these, can work out the grandTotal
var self = this;
self.lines = ko.observableArray([new CartLine()]); // Put one line in by default
};
ko.applyBindings(new Cart());
</script>
答案 0 :(得分:1)
所以这里有一些问题。首先,您对下拉列表的绑定格式不正确
<select data-bind="options: products,
optionsText: 'name',
value: id,
optionsCaption:'--Select--'">,
value: $parent.product
</select>
Value字段在数据绑定中声明为属性&#39; id&#39;我在视图模型中看不到。外部的值绑定(&#39;值:$ parent.product&#39;)绑定到有效属性,但它不在数据绑定中。看起来应该更像这样:
<select data-bind="options: products,
optionsText: 'name',
value: product">
</select>
注意:我删除了optionsCaption,因为它会覆盖您的产品&#39; object(具有名称,价格和数量的对象),只包含optionsCaption中的字符串。这会混淆任何依赖于&#39;产品&#39;对象属性以后。
至于您希望显示的其他字段:
<td><span data-bind="value: price" /></td>
<td><input data-bind="value: quantity" /></td>
<td><span data-bind="value: subtotal" /></td>
这些目前绑定到viewModel属性的价格,数量和小计。这些都没有改变(并且跨度应该被绑定到&#39; text&#39; not&#39; value&#39;)。所以我们需要将这些字段绑定到由下拉列表设置的对象,如下所示:
<td><span data-bind="text: product().price" /></td>
<td><input data-bind="value: product().quantity" /></td>
<td><span data-bind="text: product().total" /></td>
这将显示&#39; price&#39;的正确值。和&#39;数量&#39;。但是,这些值不是可观察的值,并且在更改时不会更新任何计算值。因此,我们需要这些属性是可观察的,以便通过在数量字段中键入并查看总更新来获得完整的响应感。我更喜欢创建JS对象来保存这些可观察属性的集合:
function Product(data){
data = data || {};
var self = this;
self.name = ko.observable(data.name || "");
self.price = ko.observable(data.price || "0");
self.quantity = ko.observable(data.quantity || "0");
self.total = ko.computed(function(){
return self.price() * self.quantity();
});
}
我也将总计函数移到了这个对象中,只是为了保持一致性 要使用此函数,您可以通过传入具有适当属性的对象来调用它,或者无需调用它,它将被初始化为
{name: "", price: "0", quantity: "0"}.
这也意味着我们必须更改您的产品列表以使用此新对象,否则该列表中的任何内容都不会具有可观察的属性。你可以包装新产品()&#39;围绕您正在使用的现有JS对象:
var _products = [
new Product({
"name": "1948 Porsche 356-A Roadster",
"price": 53.9
, quantity: 1
}),
new Product({
"name": "1948 Porsche Type 356 Roadster",
"price": 62.16
, quantity: 1
}),
new Product({
"name": "1949 Jaguar XK 120",
"price": 47.25
, quantity: 1
}),
new Product({
"name": "1952 Alpine Renault 1300",
"price": 98.58
, quantity: 1
}),
new Product({
"name": "1952 Citroen-15CV",
"price": 72.82
, quantity: 1
}),
new Product({
"name": "1956 Porsche 356A Coupe",
"price": 98.3
, quantity: 1
}),
new Product({
"name": "1957 Corvette Convertible",
"price": 69.93
, quantity: 1
})];
你可以看到我在这个小提琴中提到的所有变化的全部内容: http://jsfiddle.net/7e0vujf5/11/