Ko.computed函数更新两次

时间:2013-10-01 09:59:46

标签: javascript jquery knockout.js tags tag-it

由于数据是通过AJAX加载的,我需要在数据到达时更新数据。

在页面加载时,我在数据库中收集项目。然后根据选择的项目(self.SelectedProject)加载任务和标签的数据。

self.Projects = ko.observableArray();
self.Tasks = ko.observableArray();
self.Tags = ko.observableArray();
self.SelectedProject = ko.observable();  // Chosen Project-object...

对于初始化,我加载第一个项目的数据:

self.SelectedProject(self.Projects()[0]);          // Choose first returned Project... 

然后我继续填充我的标记帮助数组:

ko.computed(function () {  
    // must be ko.computed as else will not update when data arrives for Tags and Tasks (which are likely to be empty at load time)...

    // Empty projectAvailableTags before refill...
    self.SelectedProject().projectAvailableTags([]);

    // First populate current project's "projectAvailableTags"-array with values...
    for (var j = 0, jlen = self.Tags().length; j < jlen; j++) {
        self.SelectedProject().projectAvailableTags().push(self.Tags()[j].TagName());
    }

    for (var i = 0, ilen = self.Tasks().length; i < ilen; i++) {
        //---- Populate each TaskTag-array with Tags...
        for (var j = 0, jlen = self.Tags().length; j < jlen; j++) {
            if (self.Tags()[j].TagTaskId() === self.Tasks()[i].TaskId) {
                self.Task()[i].TaskTags.push(self.Tags()[j]);
                // Populate the different tag-Arrays...
                var tagtype = self.Tags()[j].TagType;
                switch (tagtype()) {
                    case 0: self.Tasks()[i].Location().push(self.Tags()[j].TagName()); break;
                    case 1: self.Tasks()[i].Manager().push(self.Tags()[j].TagName()); break;
                    case 2: self.Tasks()[i].Employee().push(self.Tags()[j].TagName()); break;

                }
            }
        }

    };
});

这可能看起来很奇怪,也许我这样做会不必要地复杂化。 我使用http://aehlke.github.com/tag-it/作为标记管理器,它只需要一个包含TagNames的数组。因此我还没想出如何直接使用Tags() - 数组,尽管我喜欢这样。

任务以手风琴形式呈现,我希望在内容面板中应用Task-tags,而我使用Project-tags作为自动完成功能的tagSource ......

但是我无法弄清楚为什么我的标签应用了ko.computed应用了2次而它们没有被应用,除非我重新选择没有它的项目。

1 个答案:

答案 0 :(得分:1)

我认为你有点忽略了计算可观测量的重点。计算的observable和常规函数之间唯一真正的区别是,你可以绑定到一个计算的observable,并在它的一个组件发生变化的任何时候依赖它来自动更新。

计算的observable的example in the knockout documentation使用名/姓,这是一个很好的例子。

基于此,更新计算本身内的计算机的依赖性确实不是一个好主意。在淘汰赛的早期版本中,这实际上会创建一个无限循环引用。

我假设计算机正在运行两次,因为标签和任务都在接收新数据,这会触发更新(但由于敲除中内置的安全措施,只有一次更新)。

更好的选择是订阅SelectedProject。然后,每次可观察到的更改,您都可以重新安装所有阵列。

self.SelectedProject.subscribe(function(newValue) {
    <load your arrays here>
});