(我知道这里还有其他问题要问同样的事情;我已经尝试过了,但是他们不适用于此处)
我有一个由Knockout JS foreach
显示的集合。对于每个项目,visible
绑定是通过调用方法设置的,基于项目本身外部的内容。当外部性发生变化时,我需要重新绘制UI。
在这个小提琴中可以看到条纹版本:http://jsfiddle.net/JamesCurran/2us8m/2/
它以四个文件夹名称列表开头,并显示以“S”开头的文件夹名称。
<ul data-bind="foreach: folders">
<li data-bind="text: $data,
visible:$root.ShowFolder($data)"></li>
</ul>
<button data-bind="click:ToA">A Folders</button>
单击该按钮应显示以“A”开头的那些。
self.folders = ko.observableArray(['Active', 'Archive', 'Sent', 'Spam']);
self.letter = 'S';
// Behaviours
self.ShowFolder = function (folder)
{
return folder[0] === self.letter;
}
self.ToA = function ()
{
self.letter = 'A';
}
更新:
在Loic向我展示了这个例子的修复方法之后,我回顾了这个例子和我的实际代码之间的区别。我正在使用空对象作为字典来切换是否选择了一个项目self.Selected()[item.Id] = !self.Selected()[item.Id];
正在更改的对象已经是可观察的。我假设Knockout没有意识到列表依赖于外部可观察量,但确实如此。 Knockout缺少的是观察者实际上正在发生变化。所以,解决方案很简单:
self.Selected()[item.Id] = !self.Selected()[item.Id];
self.Selected.notifySubscribers();
答案 0 :(得分:4)
以下是我提出的建议:
你必须要了解的是,Knockout只是“回答”可观察数据的数据变化。如果可观察的更改,它将触发使用它的每个对象。通过使self.letter
成为可观察的。您可以简单地更改它的值并在self.letter()
之类的地方使用它,并在需要时自动重绘。
function WebmailViewModel() {
// Data
var self = this;
self.folders = ko.observableArray(['Active', 'Archive', 'Sent', 'Spam']);
self.letter = ko.observable('S');
// Behaviours
self.ShowFolder = function (folder)
{
return folder[0] === self.letter();
}
self.ToA = function ()
{
self.letter('A');
}
};
ko.applyBindings(new WebmailViewModel());
如果您有复杂的绑定,例如将对象存储在observable中。如果您想修改该对象,您有多种可能的选择。
self.Selected()[item.Id] = !self.Selected()[item.Id];
你可以通过制作所有“可观察的”来改变它,但如果我的记忆是正确的,它可能变得复杂。
self.Selected()[item.Id](!self.Selected()[item.Id]());
我记得我有一个类似的问题,我有依赖问题,我必须更新国家,地区,城市。我最终将它作为列表存储在一个observable中,以防止更新单个元素更改。我有这样的事情。
var path = PathToCity();
path[0] = 'all';
path[1] = 'all';
PathtoCity(path);
通过这样做,更改将是原子的,并且只有一次更新。我有一段时间没有玩淘汰赛。我不确定,但我相信我最后一次使用淘汰赛,它能够“优化”并防止重绘整个事情。但是要小心,因为如果它无法猜测你没有改变很多东西,那么它可能会重绘整个可观察树(这可能在性能方面可能会很差)
在您的示例中,我们可以对修改后的示例使用相同的行为: