KnockoutJS template 'beforeRemove' called

2019-07-27 12:30发布

问题:

My KnockoutJS template looks as follows:

       <div id="wrapper" data-bind="template: {
                                                name:'theTemplate', 
                                                foreach: cars(),  

                                                beforeRemove: function(elem) { 
                                                    console.log(elem);                                     
                                                    console.log('try removing..');
                                                    try {
                                                        jQuery(elem).hide().remove();
                                                    } catch (e) {
                                                        console.log(e);
                                                    }
                                                },

                                                afterAdd: function(elem) { 
                                                    console.log('try adding..');
                                                    try {
                                                        jQuery(elem).hide().fadeIn();
                                                    } catch (e) {
                                                        console.log(e);
                                                    }
                                                }
                                            }"></div>

When I'm removing a object from the cars() observableArray I want to hide() and remove() the element which is being removed. Except when removing a element the beforeRemove function is called three times with three different elements as parameter.

The three elements are:

  1. Comment { data=" Block 1 ", length=9, nodeName="#comment", meer...} try removing..

  2. <TextNode textContent=" "> try removing..

  3. <div class="block"> try removing..

The afterAdd behaves the same way.. Is this a bug, or is my understanding of the function incorrect?

Thanks for your time!

回答1:

I believe that's the expected behavior if your template contains those elements.

If you only want to hide/show particular elements -- say, <div> elements -- you'll want to do a jQuery selector to filter the elements down:

afterAdd: function(elem) { 
    console.log('try adding..');
    try {
        jQuery(elem).filter("div").hide().fadeIn();
    } catch (e) {
        console.log(e);
    }
}

Related: I don't recommend putting big javascript functions right inside your HTML. It clutters the HTML and mixes concern of view and view logic. I'd instead do something like this:

<div id="wrapper" data-bind="template: {
    name:'theTemplate', 
    foreach: cars,
    beforeRemove: onRemovingCar,
    afterAdd: onAddedCar
}"></div>

<script type="text/javascript">

  var viewModel = {
     onRemovingCar: function(element) { 
          console.log(element);                                     
          console.log('try removing..');
          try {
              jQuery(element).hide().remove();
          } catch (e) {
              console.log(e);
          }
      },
      onAddedCar: function(element) { 
          console.log('try adding..');
          try {
              jQuery(element).hide().fadeIn();
          } catch (e) {
              console.log(e);
          }
      }
  };

</script>