如何强制knockoutjs更新UI(重新评估绑定)

时间:2013-12-18 23:56:14

标签: javascript knockout.js

(我知道这里还有其他问题要问同样的事情;我已经尝试过了,但是他们不适用于此处)

我有一个由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();

1 个答案:

答案 0 :(得分:4)

以下是我提出的建议:

你必须要了解的是,Knockout只是“回答”可观察数据的数据变化。如果可观察的更改,它将触发使用它的每个对象。通过使self.letter成为可观察的。您可以简单地更改它的值并在self.letter()之类的地方使用它,并在需要时自动重绘。

http://jsfiddle.net/2us8m/3/

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);

通过这样做,更改将是原子的,并且只有一次更新。我有一段时间没有玩淘汰赛。我不确定,但我相信我最后一次使用淘汰赛,它能够“优化”并防止重绘整个事情。但是要小心,因为如果它无法猜测你没有改变很多东西,那么它可能会重绘整个可观察树(这可能在性能方面可能会很差)

在您的示例中,我们可以对修改后的示例使用相同的行为:

http://jsfiddle.net/2us8m/4/

相关问题