如何订阅 observableArray 项目的更改

Posted

技术标签:

【中文标题】如何订阅 observableArray 项目的更改【英文标题】:How to subscribe to change in observableArray's item 【发布时间】:2020-10-01 23:04:06 【问题描述】:

我在这里准备了一个基本的 knockout.js 小提琴:http://jsfiddle.net/utm02ohk/2/

为了完整起见,我将在这里重复部分代码:

在我看来,我有 foreach 循环,它遍历一个 observableArray 的项目:

        <div data-bind="foreach: $root.availableItems">
         <div class="switchBox">
          <div class="switchName"><strong data-bind="text: '&nbsp;' + name()"></strong></div>
           <label class="Switch">
            <input type="checkbox" data-bind="checked: state">
           </label>
         </div>
       </div>

它基本上遍历了我的 availableItems 数组中的元素:

self.availableItems([
new Item(1, "item1", state1, self.onItemStateChange),
new Item(2, "item2", state2, self.onItemStateChange),
new Item(3, "item3", state3, self.onItemStateChange)
]);

如你所见,我还有一个函数,我用 observables 初始化每个项目:

function Item(id, name, state, onChange) 
  var self = this;

  self.id = ko.observable(id);
  self.name = ko.observable(name);
  self.state = ko.observable(state);

  self.state.subscribe(function(newValue) 
    onChange(self, newValue);
  );

数组中的每个项目都有状态变量(state1、state2、state3),它们是布尔值,它们控制检查哪个复选框,哪个不检查。它们(为了这个例子)设置在 ViewModel 的开头:

var state1 = true;
var state2 = false;
var state3 = false;

实际上 state1、state2 和 state3 是从服务器映射的。我想要实现的是,在我用起始状态值初始化我的项目后,我希望它们在 state1、state2 和 state3 的每次更改时被订阅,以便根据从服务器收到的值选中或不选中复选框.

目前,它们在第一次初始化后没有被更改。我需要尽可能减少对现有代码方法的更改,因为它会影响原始代码中的许多其他内容。

这可能吗,如果可以,有人可以解释一下如何在 knockout.js 中编写代码吗?

【问题讨论】:

【参考方案1】:

如果我理解正确,我认为这将解决您的问题,只需对您现有的代码进行很少的更改: https://jsfiddle.net/sr3wy17t/

function Item(id, name, state, onChange) 
  var self = this;

  self.id = ko.observable(id);
  self.name = ko.observable(name);
  self.state = ko.observable(state);

  self.state.subscribe(function(newValue) 
    onChange(self, newValue);
  );


function ViewModel() 
  var self = this;

  var state1 = true;
  var state2 = false;
  var state3 = false;

  self.availableItems = ko.observableArray([]);
  self.activeItemss = ko.computed(function() 
    return self.availableItems().filter(function(item) 
      return item.state();
    );
  );

  self.onItemStateChange = function(item, newValue) 
    console.log("State change event: " + item.name() + " (" + newValue + ")");
  ;


  self.init = function() 
    self.availableItems([
      new Item(1, "item1", state1, self.onItemStateChange),
      new Item(2, "item2", state2, self.onItemStateChange),
      new Item(3, "item3", state3, self.onItemStateChange)
    ]);
    setInterval(() => 
      var itemNoThatChanged = Math.floor(Math.random() * 3);
      var newState = Math.random() > 0.5;
      self.availableItems()[itemNoThatChanged].state(newState)
    , 1000)
  ;



var viewModel = new ViewModel();
ko.applyBindings(viewModel);
viewModel.init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach: $root.availableItems">
  <div class="switchBox">
    <div class="switchName"><strong data-bind="text: '&nbsp;' + name()"></strong></div>
    <label class="Switch">
                    <input type="checkbox" data-bind="checked: state">
                  </label>
  </div>
</div>

(在 setInterval 函数中,您应该有一个 ajax 调用来获取更新的值)

【讨论】:

感谢您的回复。如果一个状态是另一个 ViewModel 的一部分,这会起作用吗?我可以将 pureComputed 用于 activeItems 而不是计算的吗? 我对这两个问题都这么认为——如果你有问题,那就做一个小提琴并在这里发布 感谢您的回答,但不幸的是,这并不是我的意思。我想对其进行编码,以便仅更改为 state1、state2 或 state3 会导致复选框对应新状态。您正在直接更改数组中的项目,这不是我收到服务器响应后的情况。你能帮忙吗?

以上是关于如何订阅 observableArray 项目的更改的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Knockout.js 在特定位置将项目添加/插入到 ObservableArray

如何使用 Knockout-Validation 将无效项目添加到 observableArray 以使 validObservable 无效

如何处理绑定:更改 observableArray 中的数据后的 foreach

在 knout.js 中遍历 observablearray 时,如何检索 foreach 的 ko.computed 运行总和

使用 Knockoutjs ObservableArray 确定添加或删除了哪个元素

从 Kendo UI MVVM ObservableArray 中删除所有项目