【问题标题】:Observable objects inside observableArray do not automatically update [duplicate]observableArray 中的可观察对象不会自动更新
【发布时间】:2017-04-16 11:59:13
【问题描述】:

我一直在研究动态数据绑定的 Knockout,我遇到了一种情况,我需要一个可观察数组来包含多个可观察对象。

这是我的代码:

<ul data-bind="foreach: { data: categories, as: 'category' }">
    <li>
        <ul data-bind="foreach: { data: items, as: 'item' }">
            <li>
                <span data-bind="text: category.name"></span>:
                <span data-bind="text: item"></span>
                <input type="text" data-bind="value: item"/>
            </li>
        </ul>
    </li>
</ul>

$(document).ready(function () {
            ko.applyBindings(viewModel);
        });

        var viewModel = {
            categories: ko.observableArray([
                { name: 'Fruit', items: [ko.observable('Apple'), ko.observable('Orange'), ko.observable('Banana')] },
                { name: 'Vegetables', items: [ko.observable('Celery'), ko.observable('Corn'), ko.observable('Spinach')] }
            ])
        };

当使用 oject observables 时,通常我可以修改输入文本框的值,并将该值设置为用于显示该属性的整个页面。

在我当前的示例中,我尝试对输入框执行相同的操作,但是在我修改文本框中的值后,跨度没有达到当前值。

如何使 observableArray 中的可观察对象的行为与它们是独立的可观察对象一样?

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    当我遇到这些问题时,我喜欢将它们分解为子虚拟机,这样我可以更好地控制我所在的每个上下文级别发生的事情。对于上述问题,我会做这样的事情:

    var produceVM = function (data) {
        var self = this;
    
        self.item = ko.observable(data);
    }
    
    var categoryVM = function (data) {
        var self = this;
    
        self.name = ko.observable(data.name);
        self.items = ko.observableArray();
    
        var items = ko.utils.arrayMap(data.items, function (item) {
            return new produceVM(item);
        });
    
        self.items(items);
    }
    
    var viewModel = function (data) {
        var self = this;
    
        self.categories = ko.observableArray();
    
        var categories = ko.utils.arrayMap(data, function (category) {
           return new categoryVM(category); 
        });
    
        self.categories(categories);
    }
    
    var data = [
        { name: 'Fruit', items: [ 'Apple', 'Orange', 'Banana' ] },
        { name: 'Vegetables', items: ['Celery', 'Corn', 'Spinach' ]}
    ];
    
    ko.applyBindings(new viewModel(data));
    

    我相信 ko 映射插件无需编写上述所有代码即可实现与此类似的功能。您可以将数据模型传递给它,它会为每个项目构建可观察对象。

    【讨论】:

      【解决方案2】:

      正如@nemesv 指出的那样,答案就在拐角处。

      只需将每个数组项包装到对象中,它就会完美地工作。

      这是您的视图模型的外观,这是一个有效的jsfiddle

      var viewModel = {
          categories: ko.observableArray([{
              name: 'Fruit',
              items: [
                  {name: ko.observable('Apple')},
                  {name: ko.observable('Orange')},
                  {name: ko.observable('Banana')}
              ]
          }, {
              name: 'Vegetables',
              items: [
                  {name: ko.observable('Celery')},
                  {name: ko.observable('Corn')},
                  {name: ko.observable('Spinach')}
              ]
          }])
      };
      

      根据我自己的经验,我不得不说,通常无论如何你都会在数组中包含对象,而不是声称没有其他用例,只是说在数组中包含对象并且能够动态更改它们,无需担心其他任何事情。

      【讨论】:

        猜你喜欢
        • 2017-03-30
        • 2012-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-15
        • 2012-10-25
        • 1970-01-01
        相关资源
        最近更新 更多