我正在使用Knockout JS,因为业务需求要求大多数(如果不是全部)逻辑由于低带宽用户而在浏览器中处理。到目前为止,除了一个问题外,它的确很棒。
我使用了许多包含级联逻辑的多选下拉列表。我有8个列表处理分层数据并改变子列表中的可选选项。
这一切都很好,直到我到达底部的2个列表,这些列表可能包含3000个项目,具体取决于父列表选择(特别是当单击“全选”时)。
问题是,在IE中,我正在运行脚本警告消息,我需要摆脱它。这是一些代码:
viewModel.BottomLevelList= ko.dependentObservable(function () {
if (this.ParentList().length === 0) { //nothing selected
return [];
}
var result = [];
var i = self.longMasterList.length;
var currentId = 0;
while (i--) {
//psuodo code:
//this.ParentList().Contains(loop-item) then
//put in return list based on some further logic
//else continue
}
return result;
}, viewModel);
我尝试过使用SO中的各种setTimeout技术来打破大型阵列并立即将控制权返回给浏览器,但没有成功。结果永远不会返回和/或observable似乎分离自己在UI中留下一个空列表。
如果我需要使用AJAX,我会这样做,但这是最后的选择,并希望将其保留在客户端。
所以我的问题归结为:
非常感谢您的帮助
答案 0 :(得分:6)
我建议您优化dependentObservable
。
当您读取任何observable时,Knockout会在Dependency Manager中向它注册一个依赖项。它包含非常简单的代码:
function registerDependency(observable) {
if (ko.utils.arrayIndexOf(dependencies, observable)) {
dependencies.push(observable);
}
}
我可以在你的伪代码中看到你正在while
循环中访问this.ParentList()。这意味着registerDependency
将被调用3000次,dependencies
数组将被扫描3000次,这对IE来说是不好的(因为它没有内置的Array.indexOf方法)。
所以我的第一个建议是:在循环之前阅读所有可观察量。
如果它没有用,我建议你继续使用setTimeout()。这有点棘手。请查看此示例:http://jsfiddle.net/romanych/4KGAv/3/
我定义了asyncObservable
。您应该传递一个包含dependentObservable的所有依赖项的数组。调用ko.toJS
时,将打开所有可观察对象。然后我们使用dependencies
数组中枚举的参数调用传递的回调函数。此函数将被评估为异步。
我已将此代码包装到ko.dependentObservable中,以便在loader
dependencies
回调
<强>更新强>: 我的代码在这个问题上过于复杂。 throttle extender会做到这一点。请查看此示例:http://jsfiddle.net/romanych/JNwhb/1/