我的示例购物车无法按预期工作淘汰js

时间:2015-06-02 14:27:09

标签: jquery knockout.js

我正在学习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>

1 个答案:

答案 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/