从外部修改knockout.js模型

时间:2012-12-12 08:06:32

标签: knockout.js

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

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,获取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中得到什么?我在想,如果可观察的数组元素被修改,如果它被数据绑定到某个东西,那么某些东西也会被修改。

4 个答案:

答案 0 :(得分:2)

ko.observableArray仅跟踪是否在集合中添加或删除项目。但是如果更改可观察数组中的项目,则UI不会自动更新。

From the documentation:

  

关键点: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
​

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

答案 3 :(得分:0)

如果您想从其他脚本更改事件,我认为最好使用subscriber in knockout