我有一个简单的模型来保存我的文件夹:
var FolderModel = {
folders: ko.observableArray([
{id:'Global', uid: 'Global', name: 'Global', count:0},
{id:'New', uid: 'New', name: 'New', count:0},
{id:'Important', uid: 'Important', name: 'Important', count:0}
]);
此模型绑定到:
<ul class="folder-tree" data-bind="foreach: FolderModel.folders">
<li>
<span data-bind="text: $data.name"></span>
<span class="count" data-bind="text: $data.count"></span>
</li>
</ul>
所以初始视图将是这样的:
然后我在另一个脚本中进行一些请求轮询:等待计数更改并更新模型。然而,我所做的一切都没有奏效。我试过了:
var match = ko.utils.arrayFirst(FolderModel.folders(), function (item) {
return c == item.uid;
});
if (match) {
match.count = counts[c];
}
c - 这是文件夹的uid。所以,我使用arrayFirst,获取observable数组中的项并更新它。
接下来我尝试了:
$.each(FolderModel.folders(), function (index, folder) {
var newFolder = FolderModel.folders()[index];
newFolder.count = counts[folder.uid];
FolderModel.folders.replace(FolderModel.folders()[index], newFolder);
});
这也让我无处可去,看起来也很傻,但我发现这是另一个SO问题How to replace a given index element in knockoutjs
我做错了什么以及我没有在knockout.js中得到什么?我在想,如果可观察的数组元素被修改,如果它被数据绑定到某个东西,那么某些东西也会被修改。
答案 0 :(得分:2)
ko.observableArray仅跟踪是否在集合中添加或删除项目。但是如果更改可观察数组中的项目,则UI不会自动更新。
关键点:observableArray跟踪数组中的对象, 不是那些对象的状态
所以你需要在count
集合中观察folders
属性
var FolderModel = {
folders: ko.observableArray([
{id:'Global', uid: 'Global', name: 'Global', count: ko.observable(0) },
{id:'New', uid: 'New', name: 'New', count: ko.observable(0) },
{id:'Important', uid: 'Important', name: 'Important', count: ko.observable(0) }
]);
最终,如果您需要更新所有属性,您必须使所有属性都可观察。有一个名为KO mapping的KO插件可以帮助你。
您的更新代码应如下所示:
var match = ko.utils.arrayFirst(FolderModel.folders(), function (item) {
return c == item.uid;
});
if (match) {
match.count(counts[c]); // because count is now observable
}
这是你玩的JSFiddle。
答案 1 :(得分:2)
如果我理解正确 - 您无法更新ko.observableArray
中元素的属性并触发对阵列的更新。你需要这样做:
folders: ko.observableArray([
{ id: ko.observable('Global'), uid: ko.observable('Global'), name: ko.observable('Global'), count: ko.observable(0)}
]);
答案 2 :(得分:2)
你只需要一个文件夹作为Knockout的视图模型来捕获更改或使用observableArray
方法来更改数组:
var Folder = function (id, uid, name, count) {
// things that don't change don't need observables
this.id = ko.observable(id);
this.uid = ko.observable(uid);
this.name = ko.observable(name);
this.count = ko.observable(count);
};
var FolderModel = {
folders: ko.observableArray([
{id:'Global', uid: 'Global', name: 'Global', count:0},
{id:'New', uid: 'New', name: 'New', count:0},
{id:'Important', uid: 'Important', name: 'Important', count:0}
])
};
var FolderModelNew = {
folders: ko.observableArray([
new Folder('Global', 'Global', 'Global', 0),
new Folder('New', 'New', 'New', 0),
new Folder('Important', 'Important', 'Important', 0)
])
};
var vm = {
folderModel: FolderModel,
folderModelNew: FolderModelNew
};
ko.applyBindings(vm);
vm.folderModel.folders()[1].name = '111'; // nothing
vm.folderModel.folders.splice(0, 1, {id:'Global', uid: 'Global', name: '000', count:0}); // updated
vm.folderModelNew.folders()[1].name('111'); // updated
答案 3 :(得分:0)
如果您想从其他脚本更改事件,我认为最好使用subscriber in knockout