1

我有一个简单的模型来保存我的文件夹:

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>

所以初始视图将是这样的:

  • 全球 (0)
  • 新 (0)
  • 重要 (0)

然后我在另一个脚本中做一些请求轮询:等待计数改变和更新模型。然而,我所做的一切都没有奏效。我试过了:

var match = ko.utils.arrayFirst(FolderModel.folders(), function (item) {
    return c == item.uid;
});

if (match) {
    match.count = counts[c];
}

c - 这是文件夹的 uid。所以,我使用arrayFirst,获取可观察数组中的项目并更新它。

我尝试的下一件事:

    $.each(FolderModel.folders(), function (index, folder) {
        var newFolder = FolderModel.folders()[index];
        newFolder.count = counts[folder.uid];
        FolderModel.folders.replace(FolderModel.folders()[index], newFolder);
    });

这也让我无处可去,而且看起来也很傻,但我在另一个 SO 问题上发现了这个如何在 knockoutjs 中替换给定的索引元素

我做错了什么,在 knockout.js 中没有得到什么?我在想,当可观察数组元素被修改时,如果它被数据绑定到某些东西,那么某些东西也会被修改。

4

4 回答 4

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 映射的 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,您可以在其中使用它。

于 2012-12-12T08:19:03.703 回答
2

如果我对您的理解正确 - 您无法更新 a 中元素的属性ko.observableArray并触发对数组的更新。你需要这样做:

folders: ko.observableArray([
    { id: ko.observable('Global'), uid: ko.observable('Global'), name: ko.observable('Global'), count: ko.observable(0)}
]);
于 2012-12-12T08:19:41.137 回答
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
​

小提琴:http: //jsfiddle.net/Sgc5J/

于 2012-12-12T08:20:56.993 回答
0

如果您想从另一个脚本中获取更改事件,我认为您最好在淘汰赛中使用订阅者

于 2012-12-12T08:13:02.793 回答