带有Foreach的KO模板如果条件导致afterAdd不要触发

J. *_*ell 0 knockout-2.0 knockout.js

在下面的示例中,您将看到doSomething永远不会触发.如果if: Comments从模板绑定中删除doSomething将按预期触发.有谁知道导致这种情况发生了什么?data在模板绑定处理程序上使用属性时也会发生这种情况.

我目前正在使用Knockout 2.2.1.jsfiddle http://jsfiddle.net/YADzx/2/

<div data-bind="template: { if: Comments, name: 'comments' }"></div>

<script type="tmpl" id="comments">
    <div data-bind="foreach: { data: Comments, afterAdd: $root.doSomething }">
        <div data-bind="text: name"></div>
    </div>
</script>
<script>
var vm = {
    Comments: ko.observableArray([{name:'hey'}]),
    doSomething: function (element, index, data) {
        $(element).addClass('wow');
    }
};

ko.applyBindings(vm);
vm.Comments.push({name:'foo'});
vm.Comments.push({name:'bar'});
</script>
Run Code Online (Sandbox Code Playgroud)

Mic*_*est 10

if对条件template结合使其随时更新Comments变化.然后Knockout将重新渲染整个模板,并且之前的foreach绑定状态将丢失.

根据您想要或不想要的副作用,有几种方法可以解决这个问题.

  1. 删除if选项.您的代码仍然可以正常工作,但您将拥有HTML中<div>foreach绑定.所以如果它弄乱你的布局,这不是一个好的选择.

  2. if从中拆分template并使用另一个元素(或注释语法)与if绑定.只要您使用的是Knockout 2.2.0或更高版本,这将有效.

    <script type="tmpl" id="comments">
        <!--ko if: Comments-->
        <div data-bind="foreach: { data: Comments, afterAdd: $root.doSomething }">
            <div data-bind="text: name"></div>
        </div>
        <!--/ko-->
    </script>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 而不是使用if绑定,使用visible绑定,它隐藏当前元素,不会重新呈现.

    <script type="tmpl" id="comments">
        <div data-bind="visible: Comments, foreach: { data: Comments, afterAdd: $root.doSomething }">
            <div data-bind="text: name"></div>
        </div>
    </script>
    
    Run Code Online (Sandbox Code Playgroud)

但是,要考虑的一件事是,observableArray通常不会包含假值.那是因为在JavaScript中,空数组仍然是真的.如果要测试空数组,则需要更改if: Commentsif: Comments().length.