【问题标题】:How to get my Knockout code to bind properly如何让我的淘汰赛代码正确绑定
【发布时间】:2017-10-28 02:34:02
【问题描述】:

我有一个使用 KnockoutJS 3.4.2 构建的购物车页面。我在最新的 Chrome 中对此进行了测试。 Ajax 正在加载购物车中的产品。

然后将购物车填充到 HTML 表格中。

由于某种原因,当我在 TD 中绑定“productTitle”时它可以工作,但是当我尝试在跨度中绑定它时它不会。我也尝试使用模板:<span><!--ko text: productTitle--><!--/ko--></span>,但这也行不通。

这是否与加载页面时 observableArray 可能仍然为空的事实有关?我发现当我将 'productTitle' 放入 TD 文本绑定时,文本会起作用。

由于某种原因,可观察计数不会绑定到数据绑定值的输入。也许我的 viewModel 的构建方式是错误的?

这是我的代码:

HTML

<tbody data-bind="foreach: productsInCart">
                <tr data-bind="attr: {productOptionId: productOptionId}">
                    <td></td>
                    <td class="cart-title" data-bind="text: productTitle"></td>
                    <td data-bind="text: price"></td>
                    <td>
                        @*<span><!--ko text: productTitle--><!--/ko--></span>*@
                            <div click-action="" class="qtyminus"></div>
                            <input type='text' name="quantity" data-bind="value: count" class="qty"/>
                            <div click-action="" class="qtyplus"></div>                        
                    </td>
                    <td class="cart-total" data-bind="text: total"></td>@*
                    <td><a href="@Url.Action("RemoveProductOption", "ShoppingCart", new {id = product.ProductOptionId})" class="cart-remove"></a></td>*@
                </tr>
            </tbody>

JS

$(function () {  
    var productInCart = function(data) {
        var self = this;

        self.productOptionId = ko.observable(data.ProductOptionId);
        self.price = ko.observable(data.Price);
        self.count = ko.observable(data.Count);
        self.productBrandName = ko.observable(data.ProductBrandName);
        self.productOptionName = ko.observable(data.ProductOptionName);
        self.productName = ko.observable(data.ProductName);
        self.productFriendlyUrl = ko.observable(data.ProductFriendlyUrl);

        self.productTitle = ko.computed(function () {
            return self.productName() + " " + self.productOptionName();
        });

        self.total = ko.computed(function () {
            return self.count() * self.price();
        }, self);

        return self;
    }

    function viewModel() {
        var self = this;

        self.productsInCart = ko.observableArray([]);

        $.ajax({
            type: "GET",
            url: window.cartUrl,
            dataType: "json",
            contentType: 'application/json; charset=utf-8',
            traditional: true, //// traditional option to true
            success: function (result) {
                console.log(result);
                ko.utils.arrayForEach(result, function (data) {
                    self.productsInCart.push(new productInCart(data));
                });
                console.log(self.productsInCart());
            }
        });
    }

    var vm = new viewModel();
    ko.applyBindings(vm);
});

AJAX 正在加载的对象:

[
{
ShoppingSessionId: 2061,
ProductOptionId: 3,
Price: 26.95,
Count: 1,
ProductBrandName: "G-Star",
ProductOptionName: "Maat 36/36",
ProductName: "G-Star Loose, 340166",
ProductFriendlyUrl: "g-star-3301-loose-dus",
TaxId: 1,
TaxRate: 21,
FirstProductImageId: 7,
Id: 48
}
]

无法绑定错误之一:

Uncaught ReferenceError: Unable to process binding "value: function (){return count }"
Message: count is not defined
    at value (eval at parseBindingsString (knockout-3.4.2.js:280), <anonymous>:3:58)
    at m (knockout-3.4.2.js:470)
    at Function.Uc (knockout-3.4.2.js:204)
    at Function.Vc (knockout-3.4.2.js:201)
    at Function.U (knockout-3.4.2.js:200)
    at Object.a.m.a.B (knockout-3.4.2.js:193)
    at init (knockout-3.4.2.js:472)
    at knockout-3.4.2.js:309
    at Object.w (knockout-3.4.2.js:149)
    at knockout-3.4.2.js:308

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    注意:至此,问题是由正在扩充 KO 绑定的第三方库 (StackTable) 引起的。

    您的代码看起来很简单?我注意到&lt;span&gt;&lt;/span&gt; 被注释掉了。这是你提到的有问题的跨度吗?

    如果是这样,我建议将绑定放在&lt;span&gt; 元素本身上。我不确定文本绑定是否支持虚拟标签使用。

    替换:

    <span><!--ko text: productTitle--><!--/ko--></span>
    

    与:

    <span data-bind="text: productTitle"></span>
    

    此外,作为“最佳实践”的一种方式,我不会将单个元素推送到数组中。每次推送都会导致淘汰赛重新评估依赖关系,并且会/可能会导致重绘(即对性能不太好)。而是:

    1. 构建一个本地普通的旧 JavaScript 数组。
    2. 将物品推入其中。
    3. 将可观察数组的值设置为刚刚构建的本地数组的值。

    我还将foreach 包装在逻辑检查中,以确定数组不是空/未定义或空的。防止任何潜在的绑定错误。

    【讨论】:

    • 使用两个 HTML 模板工具有什么意义 - Razor Knockout?我从来没有真正理解这一点。有什么 Knockout 不能做的事情吗?
    • 是的。服务器渲染。 SEO 在大多数网站中都发挥着重要作用,因此在某些情况下,服务器渲染可能至关重要。
    • 好吧,但是你在服务端渲染的时候,为什么要在客户端渲染呢?无论如何,有两个注意事项:text 绑定在虚拟元素上受支持(所有绑定都是),您的替换建议不会改变任何内容。并且:我同意您的 3 个步骤,但可以使用 Array#map(或 ko.utils.arrayMap)将它们合并为一个。
    • 好吧,考虑一下,从头开始“所有绑定”。例如,“属性”实际上没有意义。
    • 嗨皮姆,感谢您对数组填充的回答和建议。不幸的是,跨度中的绑定没有像你提到的那样工作。我试图解释但失败了抱歉。我确实在 ASP.NET MVC Razor 中进行了 porgram。我得到的错误是 productTitle 无法绑定。你奇怪的是:这有效 -> 这失败了 -> 跨度>。我只是不明白
    猜你喜欢
    • 2016-11-15
    • 1970-01-01
    • 2013-02-04
    • 2014-10-23
    • 2013-10-31
    • 2013-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多