【问题标题】:How to subscribe to change in observableArray's item如何订阅 observableArray 项目的更改
【发布时间】: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 中编写代码吗?

【问题讨论】:

    标签: javascript arrays knockout.js observable


    【解决方案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 会导致复选框对应新状态。您正在直接更改数组中的项目,这不是我收到服务器响应后的情况。你能帮忙吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    • 2018-02-21
    • 2023-03-26
    • 2016-12-03
    相关资源
    最近更新 更多