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;
答案 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>