Knockoutjs foreach绑定中的方法会被顺序调用两次



即使绑定的结果看起来不错,createSubList也会在场景后面按顺序调用两次。您可以在浏览器的控制台中查看它。如何避免这种行为?

<section>
<!-- ko foreach : list1 -->
<div data-bind='text:$data'></div>
<!-- ko foreach : $root.createSubList($data) -->    
<div data-bind='text:$data'></div>
<!-- /ko -->
<!-- /ko -->
</section>
function VM(){
var self = this;
self.list1 = [1, 2, 3, 4, 5];
self.createSubList = function(index){
// this method gets called twice, why?
console.log(index);
return ['Sub1'];
}
}
ko.applyBindings(new VM())

https://jsfiddle.net/7eL2ur8o/2/

发生这种情况的原因可能有很多。在这种情况下,它很可能在创建绑定时对其进行一次评估以获得初始值,并在实际绑定DOM时进行第二次评估。意识到KO是用来跟踪变化的,而知道某件事发生了变化的一种方法是重新评估可观察的属性。

要了解为什么在这种特殊情况下会发生两次,可能最简单的方法是加载未优化版本的KO并设置断点。

但还有一点更重要。您有一个以绑定中使用的create...开头的方法名称。您应该意识到,您使用的是有影响力的编程风格,其中Knockout的绑定通常用于声明性风格。

换句话说,你应该努力让你的可观察属性没有副作用,最好在相同的上下文中给出相同的结果。这里有一个更KO风格的代码版本:

function VM(){
var self = this;
var list1Input = [1, 2, 3, 4, 5];

function createSubList(index){
// this method gets called once
console.log(index);
return ['Sub1'];
}

self.list1 = list1Input.map(function(i){
return {
label: i,
subItems: createSubList(i)
};
});
}
ko.applyBindings(new VM())
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<section>
<!-- ko foreach : list1 -->
<div data-bind='text: $data.label'></div>
<!-- ko foreach : subItems -->    
<div data-bind='text: $data'></div>
<!-- /ko -->
<!-- /ko -->
</section>

最新更新