【问题标题】:Observing properties of an array that is being observed in KnockoutJS观察在 KnockoutJS 中观察到的数组的属性
【发布时间】:2025-12-20 06:30:10
【问题描述】:

我正在开发一个 ASP.Net MVC 应用程序。我的操作是返回一个带有模型的视图,该模型是一个对象数组(具有名称、ID、IsViewable 等属性的类)。

var model = @Model.ToJson(); // done via extension call

我想观察这个数组,所以每当它发生变化时,我都可以更新已绑定到模板的表。

var viewModel = {
    accounts = ko.observableArray(model)
}

这适用于从数组中添加和删除元素。但是,我还希望在其中一个帐户中的属性更改(即名称或 ID)时更新模板。

在 KnockoutJS 网站上,它说:当然,如果您愿意,您可以使这些属性可观察,但这是一个独立的选择。这是我不知道该怎么做。

我尝试过这样的事情没有成功:

var viewModel = {
    accounts = ko.oservableArray([])
}

for(var i = 0; i < model.length; i++) {
    ko.observableArray(model[i]);
    viewModel.accounts.push(model[i]);
}

如果需要,我可以发布模板和表格。

【问题讨论】:

    标签: model-view-controller templates knockout.js observable


    【解决方案1】:

    您应该查看knockout.mapping 插件。我认为它可以满足您的所有需求。

    【讨论】:

    • 我确实以某种方式错过了那个插件。感谢您的提醒,Serge!
    【解决方案2】:

    这是另一种有效且不需要映射插件的方法:

    var model = @Model.ToJson();
    
    var viewModel = {
        accounts: ko.observableArray([]),
    
        fromJS: function(js) {
            for (var i = 0; i < js.length; i++) {
                this.accounts.push({ 
                    Property1: ko.observable(js[i].Property1),
                    Property2: ko.observable(js[i].Property2),
                    Property3: ko.observable(js[i].Property3)
                });
            }
        }
    };
    
    viewModel.fromJS(model);
    ko.applyBindings(viewModel);
    

    【讨论】:

      【解决方案3】:

      我最终得到了这个工作,所以我想我会与任何可能遇到同样问题的人分享。

      您需要将数组项包装在 JavaScript 类中。然后在构造函数中,将每个属性设置为可观察:

      var model = @Model.ToJson();
      
      var viewModel = {
          accounts = ko.observableArray(ko.utils.arrayMap(model, function(account) {
              return new AccountWrapper(account);
          }))
      };
      
      function AccountWrapper(account) {
          this.Property1 = ko.observable(account.Propery1);
          this.Property2 = ko.observable(account.Propery2);
          this.Property3 = ko.observable(account.Propery3);
      }
      
      ko.applyBindings(viewModel);
      

      如果您想直接修改其中一项以查看更改,您可以执行以下操作:

      viewModel.accounts()[3].Name('My Name Changed');
      

      并且您仍然可以在添加或删除项目时收到通知:

      viewModel.accounts.remove(viewModel.accounts()[4]);
      

      【讨论】:

      • @Model.ToJson() 是什么意思?你的模型有 ToJson 方法吗?谢谢