使用knockout.viewmodel时如何更新数组成员?

时间:2015-09-20 09:41:24

标签: knockout.js

knockout.viewmodel插件包含" arrayChildId"的选项。用于"识别[数组成员]以进行更新",according to the documentation。但是,pushFromModel函数和updateFromModel效用函数似乎都不像那样工作。

我做了一个示例(下面),展示了这些函数是如何工作的 - 前者用更新的元素替换整个数组,而前者在数组的末尾推送更新元素的新副本,忽略ArrayChildId属性。

knockout.viewmodel视图模型中更新数组成员的正确方法是什么?如果我只是自己定位数组成员并手动更新,为什么还有ArrayChildId选项呢?



var model = {
  Crews: [{
    CrewId: 1,
    CrewName: "test 1"
  }, {
    CrewId: 2,
    CrewName: "test 2"
  }]
};

var viewModel = ko.viewmodel.fromModel(model, {
  arrayChildId: {
    "{root}.Crews": "CrewId"
  }
});

viewModel.updateRecord = function() {
  ko.viewmodel.updateFromModel(viewModel, {
    Crews: [{
      CrewId: 1,
      CrewName: "test update 1"
    }]
  })
};
viewModel.updateRecord2 = function() {
  viewModel.Crews.pushFromModel({
    CrewId: 1,
    CrewName: "test update 1"
  })

};


ko.applyBindings(viewModel);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://coderenaissance.github.com/knockout.viewmodel/knockout.viewmodel.min.js"></script>
<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>name</th>
    </tr>
  </thead>
  <tbody data-bind="foreach: Crews">
    <tr>
      <td data-bind="text: CrewId"></td>
      <td data-bind="text: CrewName"></td>
    </tr>
  </tbody>
</table>
<button data-bind="click: updateRecord">Update Record Using updateFromModel</button>
<button data-bind="click: updateRecord2">Update Record Using pushFromModel</button>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

updateFromModel假设您收到了更新的模型(即包含所有内容,而不仅仅是delta),并根据该模型对视图模型进行delta更改。换句话说,“替换整个数组”对于您的测试用例是预期的效果。 (实际上ID为1的对象会在您的情况下收到更新,它看起来只是替换。)

在下面比较,我突出显示视图的增量更改,证明它确实有效。

pushFromModel并非旨在考虑arrayChildId。它应用映射选项(extend,apend等)并将结果对象推送到目标数组上。

var model = {
  Crews: [
    {CrewId: 1, CrewName: "test 1"},
    {CrewId: 2, CrewName: "test 2"}
  ]
};

var vm = ko.viewmodel.fromModel(model, {
  arrayChildId: {
    "{root}.Crews": "CrewId"
  }
});

vm.updateFromModel = function() {
  ko.viewmodel.updateFromModel(vm, {
    Crews: [
      {CrewId: 1, CrewName: "test 1"},
      {CrewId: 2, CrewName: "test 2 new"},
      {CrewId: 3, CrewName: "test 3"}
    ]
  });
};
vm.pushFromModel = function() {
  vm.Crews.pushFromModel({
    CrewId: 1,
    CrewName: "test update 1"
  });
};
vm.yellowFadeIn = function(element, index, data) {
  var $row = $(element).filter("tr");
  $row.css({ backgroundColor: 'yellow' });
  setTimeout(function () {
    $row.css({ backgroundColor: '' });
  }, 500);
};

ko.bindingHandlers.text.realupdate = ko.bindingHandlers.text.update;
ko.bindingHandlers.text.update = function (element) {
  var $elem = $(element);
  ko.bindingHandlers.text.realupdate.apply(this, arguments);
  $elem.css({color: 'red'});
  setTimeout(function () {
    $elem.css({color: ''});
  }, 500);
};
ko.applyBindings(vm);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="http://coderenaissance.github.com/knockout.viewmodel/knockout.viewmodel.min.js"></script>

<button data-bind="click: updateFromModel">updateFromModel</button>
<button data-bind="click: pushFromModel">pushFromModel</button>

<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>name</th>
    </tr>
  </thead>
  <tbody data-bind="foreach: {data: Crews, afterAdd: yellowFadeIn }">
    <tr>
      <td data-bind="text: CrewId"></td>
      <td data-bind="text: CrewName"></td>
    </tr>
  </tbody>
</table>