【问题标题】:My sample shopping cart is not working as expected knockout js我的示例购物车没有按预期工作淘汰 js
【发布时间】:2015-06-02 14:27:09
【问题描述】:

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

【问题讨论】:

  • 您没有关闭data-bind 元素中的data-bind 属性。此外,在您的 &lt;span&gt; 元素中,您需要使用 text: 而不是 value: 绑定。

标签: jquery knockout.js


【解决方案1】:

所以这里有一些问题。首先,您对下拉列表的绑定格式不正确

<select data-bind="options: products, 
                           optionsText: 'name', 
                           value: id,
                           optionsCaption:'--Select--'">,
                           value: $parent.product
                           </select>

Value 字段在数据绑定中声明为我在视图模型中看不到的属性“id”。外部的值绑定 ('value: $parent.product') 绑定到一个有效的属性,但它不在数据绑定内部。它应该看起来更像这样:

<select data-bind="options: products, 
                           optionsText: 'name',
                            value: product">
                           </select>

注意:我删除了 optionsCaption,因为它只会用 optionsCaption 中的字符串覆盖您的“产品”对象(具有名称、价格和数量的对象)。这会弄乱以后依赖“产品”对象属性的任何绑定。

至于您希望显示的其他字段:

    <td><span data-bind="value: price" /></td>
    <td><input data-bind="value: quantity" /></td>
    <td><span data-bind="value: subtotal" /></td>

这些当前绑定到 viewModel 属性价格、数量和小计。这些都没有改变(并且跨度应该绑定到“文本”而不​​是“值”)。因此,我们需要将这些字段绑定到由下拉菜单设置的对象,如下所示:

    <td><span data-bind="text: product().price" /></td>
    <td><input data-bind="value: product().quantity" /></td>
    <td><span data-bind="text: product().total" /></td>

这将显示“价格”和“数量”的正确值。然而,这些值不是可观察的,并且在它们发生变化时不会更新任何计算值。因此,我们需要这些属性是可观察的,以便通过在数量字段中输入并查看总更新来获得完整的响应感。我更喜欢创建 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"}.

这也意味着我们必须更改您的产品列表才能使用这个新对象,否则该列表中的任何内容都不会具有可观察的属性。您可以将 'new Product()' 包裹在您正在使用的现有 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/

【讨论】:

  • 感谢您提供出色的工作代码。因此,我是淘汰赛的新手,所以我很难理解几个领域。您能否详细讨论如何在下拉菜单和其他输入之间建立关系。假设当我从下拉列表中选择任何数据时,相应的输入框会被填满,如数量、价格等。只是告诉这么简单的方式,结果我可以理解当任何用户从下拉列表中选择任何数据时,数量、价格是如何被填满的.谢谢
  • 是的,很高兴我能帮上忙。输入和下拉列表之间的关系是从 CartLine 视图模型属性“产品”创建的。在下拉列表中,您可以看到我们绑定了“值:产品”。这使得在下拉列表中选择的任何选项都隐藏在 CartLine 函数的变量“self.product”中。当我们对其他输入进行绑定时,您可以看到我们正在绑定到“product().price”和“product().quantity”。此处的产品与下拉列表中绑定的产品相同。希望这很清楚!
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2012-07-27
  • 1970-01-01
  • 2016-06-14
  • 2013-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多