我正在尝试修改我的基础数据对象,并让页面上的能够更新并显示新列。数据对象更新正常,但不会触发重新呈现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'
}
答案 0 :(得分:0)
你并没有真正更新observable,而是向它包含的对象添加一个新字段。
在向KO数组中的对象追加一些属性后尝试使用vm.items.valueHasMutated();
。
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;
您在此处所做的实际上是告诉可观察数组值已更改,所有订阅者都会通知。
如果你看一下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;
};