【问题标题】:Knockout Nested Computed Property binds on page load but fails after Parent Computed Property update敲除嵌套计算属性在页面加载时绑定,但在父计算属性更新后失败
【发布时间】:2014-08-04 06:16:41
【问题描述】:

我正在尝试创建一个菜单,当您单击代表多个组之一的按钮时,会出现一张图像,显示最受欢迎的产品。我知道这可以更简单地完成,但我正在尝试使用现有的数据模型。

我正在尝试将 img 元素绑定到属性 (ProductImageUrl),该属性是嵌套 ko.computed 对象 (MostPopularProduct) 的属性,它是父 ko.computed 对象 (SelectedGroup) 的属性。

viewModel.SelectedGroup().MostPopularProduct().ProductImageUrl

当页面加载时,一切都按预期工作,数据绑定到图像工作正常。但是,当我单击 Group2 按钮时,出现以下数据绑定错误:

Uncaught TypeError: Unable to parse bindings.
Bindings value: attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl}
Message: undefined is not a function VM133:3

嵌套的 ko.computed 属性 MostPopularProduct() 有一个值并在页面加载时正确绑定,但是在单击按钮后,在父 Computed 属性更新后,嵌套的 ko.computed 属性 MostPopularProduct() 未定义。

我怀疑这个问题与 viewModel 属性的数据绑定有关,该属性是嵌套的 ko.computed 属性的属性。

这里是 jsfiddle: http://jsfiddle.net/boaldave/n5KQr/9/

<div id="GroupSelector">
    <img data-bind="attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl}">

    <ul id="Menu" data-bind="foreach:Groups">
        <li>
            <button data-bind="click: $parent.HandleButtonClick">
                <span data-bind="text: $data.GroupName"></span>
            </button>
        </li>
    </ul>
</div>

<script>

viewModel = {
    Groups: 
    [
        {
            GroupName:"Group1",
            MostPopularProductID: "Product1"
        },
        {
            GroupName:"Group2",
            MostPopularProductID: "Product2"
        }
    ],
    Products:
    [
        {
            ProductID: "Product1",
            ProductImageUrl: "http://placehold.it/100x100"
        },
        {
            ProductID: "Product2",
            ProductImageUrl: "http://placehold.it/200x200"
        }
    ]
};

// Since the data model above comes from a database, I extend the 
// viewModel properties with ko.observable and ko.computed properties:

viewModel.SelectedGroupName = ko.observable("Group1");

viewModel.SelectedGroup = ko.computed(function() {
    return ko.utils.arrayFirst(viewModel.Groups, function(item) {
        return item.GroupName === viewModel.SelectedGroupName();
        });
    }, viewModel);

viewModel.SelectedGroup().MostPopularProduct = ko.computed(function ()  {
    return ko.utils.arrayFirst(viewModel.Products, function (item) {
        return item.ProductID === viewModel.SelectedGroup().MostPopularProductID;
        });
    }, viewModel);

viewModel.HandleButtonClick = function(s, e) {
    viewModel.SelectedGroupName(s.GroupName);
};

var groupSelectorDiv = document.getElementById('GroupSelector');
if (groupSelectorDiv) {
    ko.applyBindings(viewModel, groupSelectorDiv);
}

</script>

【问题讨论】:

  • 这一行viewModel.SelectedGroup().MostPopularProduct = ko.computed(function () { 仅将MostPopularProduct 附加到Groups 数组中的“Group1”项。第二项没有。

标签: knockout.js


【解决方案1】:

JSFiddle:http://jsfiddle.net/jhmRc/

尝试改变

viewModel.SelectedGroup().MostPopularProduct = ko.computed(function ()  {

viewModel.SelectedGroup.MostPopularProduct = ko.computed(function ()  {

然后改变这个

<img data-bind="attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl>

<img data-bind="attr:{src: SelectedGroup.MostPopularProduct().ProductImageUrl}>

在您的示例中,您将 MostPopularProduct 分配给计算的值,这就是它在页面加载时起作用但在值更改后不起作用的原因。

第二种方式将其添加到计算对象本身

【讨论】:

  • 我去吃午饭,然后回来,心想,我敢打赌,我将嵌套的 MostPopularProduct 计算属性添加到初始 SelectedGroup 对象,因此当它在单击时被覆盖时,新的 SelectedGroup 对象不知道嵌套的 MostPopularProduct。感谢您证实我的怀疑!
  • 我更正了 jsfiddle,现在它可以工作了。谢谢Thunderduky!
  • 这是我最终得到的实际 jsfiddle。它允许与原始标记进行数据绑定,如下所示: jsfiddle.net/boaldave/3Sk6Y/3
猜你喜欢
  • 1970-01-01
  • 2019-06-18
  • 2018-01-02
  • 2020-09-09
  • 2014-07-22
  • 2013-03-02
  • 2013-08-16
  • 2012-01-27
  • 1970-01-01
相关资源
最近更新 更多