2012-12-12 33 views
1

我有保持我的文件夾,一個簡單的模型:修改從它的外部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,獲取可觀察數組中的項目並更新它。

接下來的事情我想:

$.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?我在想,可觀察的數組元素會被修改,如果它是數據綁定的東西,那麼也會修改一些東西。

回答

1

你只需要一個文件夾是一個視圖模型淘汰賽趕上變化,或使用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/

2

如果項目被添加或從集合中刪除的ko.observableArray只跟蹤變更事件。但是,如果您更改可觀察數組內的項目,UI將不會自動更新。

From the documentation:

關鍵點:一個observableArray跟蹤哪些對象是在數組中, 不是那些

所以,你需要做的folders集合觀察到內部的count性對象的狀態

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 mapping的插件可以幫助你。

而且你的更新代碼應該是這樣的:

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,你玩它。

2

如果我正確理解你 - 你不能更新ko.observableArray中元素的屬性並觸發數組的更新。你需要這樣做:

folders: ko.observableArray([ 
    { id: ko.observable('Global'), uid: ko.observable('Global'), name: ko.observable('Global'), count: ko.observable(0)} 
]);