KnockoutJS - 在属性添加到对象时添加列

时间:2016-05-13 09:48:13

标签: knockout.js

我正在尝试修改我的基础数据对象,并让页面上的能够更新并显示新列。数据对象更新正常,但不会触发重新呈现UI。

我有什么不明白的?

http://jsfiddle.net/Xpx7f/198/

<table>
    <thead>
        <tr data-bind="foreach: columnNames">
            <th> <span data-bind="text: $data"></span>

            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: items">
        <tr data-bind="foreach: $parent.columnNames">
            <td><input data-bind="value: $parent[$data]"></td>
        </tr>
    </tbody>
</table>

和Javascript:

var vm;

window.onload = function() {
var VM = function () {
    var self = this;
    self.items = ko.observableArray();
    self.columnNames = ko.computed(function () {
        if (self.items().length === 0)
            return [];
        var props = [];
        var obj = self.items()[0];
        for (var name in obj)
            props.push(name);
        return props;


    });

};
vm = new VM();

ko.applyBindings(vm);

vm.items.push({
    'Name': 'John',
    'Age': 25
});
vm.items.push({
    'Name': 'Morgan',
    'Age': 26
});

// Add an extra property to each object
for (var i = 0; i < vm.items().length; i++) {
        vm.items()[i].Weight = '50kg';
}
// ????? Table should update with new column 'Weight'

}

1 个答案:

答案 0 :(得分:0)

你并没有真正更新observable,而是向它包含的对象添加一个新字段。

在向KO数组中的对象追加一些属性后尝试使用vm.items.valueHasMutated();

&#13;
&#13;
var vm;

window.onload = function() {
  var VM = function() {
    var self = this;
    self.items = ko.observableArray();
    self.columnNames = ko.computed(function() {
      if (self.items().length === 0)
        return [];
      var props = [];
      var obj = self.items()[0];
      for (var name in obj)
        props.push(name);
      return props;


    });

  };
  vm = new VM();

  ko.applyBindings(vm);

  vm.items.push({
    'Name': 'John',
    'Age': 25
  });
  vm.items.push({
    'Name': 'Morgan',
    'Age': 26
  });

  for (var i = 0; i < vm.items().length; i++) {
    vm.items()[i].Weight = '50kg';
  }
  vm.items.valueHasMutated();

}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
  <thead>
    <tr data-bind="foreach: columnNames">
      <th> <span data-bind="text: $data"></span>

      </th>
    </tr>
  </thead>
  <tbody data-bind="foreach: items">
    <tr data-bind="foreach: $parent.columnNames">
      <td>
        <input data-bind="value: $parent[$data]">
      </td>
    </tr>
  </tbody>
</table>
&#13;
&#13;
&#13;

您在此处所做的实际上是告诉可观察数组值已更改,所有订阅者都会通知

如果你看一下Knockout可观察数组推送的实现,你可以看到每次推送都适用相同的逻辑 - 他们称之为valueHasMutated()

    ko.observableArray['fn']['push'] = function () {
        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
        // (for consistency with mutating regular observables)
        var underlyingArray = this.peek();
        this.valueWillMutate();
        this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);
        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
        this.valueHasMutated();
        // The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array instead.
        return methodCallResult === underlyingArray ? this : methodCallResult;
    };