$ .remove()是从分离的元素中删除事件?

时间:2013-06-12 20:16:54

标签: javascript dom jquery

当鼠标悬停在列表项目上时,该元素将被附加到列表项目,当鼠标移出时,该元素将被分离。

单击该元素时,它将被分离,然后从DOM中删除它所属的列表项。

我的HTML:

<div id="cart">
    <ul>
        <li> <a data-item="a">item A</a></li>
        <li> <a data-item="b">item B</a></li>
        <li> <a data-item="c">item C</a></li>
        <li> <a data-item="d">item D</a></li>            
        <li> <a data-item="e">item E</a></li>
        <li> <a data-item="f">item F</a></li>
        <li> <a data-item="g">item G</a></li>
        <li> <a data-item="h">item H</a></li>         
    </ul>    

</div>

我的JavaScript:

  function plugin(node, opts){
    var self = this;
        delKnob = $('<i />').text('×');

    this.cart = $(node);

    delKnob
      .on('click', function(){              
        var item = $(this).parent().find('[data-item]').data('item');
        $(this).detach();
        self.remove(item);
      });

    this.cart
      .on('mouseenter', 'li', function(){
        delKnob.appendTo(this);
      })
      .on('mouseleave', 'li', function(){
        delKnob.detach();
      });
  }

  plugin.prototype = {
    remove: function(item){
      var li = this.cart.find('[data-item="' + item + '"]').closest('li');
      li.addClass('removing');
      setTimeout(function(){
        li.remove();   
      }, 500);    
    }
  };

new plugin('#cart');

我设置的fiddle example类似于我的代码。

问题是来自此元素的click侦听器也会被列表项删除,即使该元素在$.remove()触发之前被分离,因此它不应受到影响。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:6)

你认为正确的是正确的,除了当你分离delKnob时,你的鼠标会立即进入包含它的li,这意味着它会被重新附加,所以li已被删除,delKnob仍然是孩子,因此也会被删除。

我通过在代码中添加console.log()对此进行了测试:

this.cart.on('mouseenter', 'li', function () {
    console.log("delKnob attached!");
    delKnob.appendTo(this);
})

通过移除delKnob

中的setTimeout来解决此问题
setTimeout(function () {
    li.find('.delKnob').detach();
    li.remove();
}, 500);

这假设将类delKnob添加到元素中。

演示:http://jsfiddle.net/AHjRN/

作为旁注,我会简化整个事情,只需为delKnob添加li。然后你只是显示/隐藏它们,而不必担心删除处理程序。它还简化了代码:

function plugin(node, opts) {
      this.cart = $(node);

      this.cart.find('li').append($('<i class="delKnob"/>').text('×').hide());

      this.cart.on('click', '.delKnob', function () {
          var li =  $(this).closest('li').addClass('removing');
          setTimeout(function () {
             li.remove();
          }, 500);
      });

      this.cart.on('mouseenter', 'li', function () {
          $(this).find('.delKnob').show();
      })
          .on('mouseleave', 'li', function () {
          $(this).find('.delKnob').hide();
      });   
};

演示:http://jsfiddle.net/F3Qdp/

答案 1 :(得分:1)

您可以使用事件委派并将事件绑定到处理任何delKnob的容器(this.cart),而不是将事件绑定到(重新)移动的.delKnob。点击后代。

delKnob = $('<i class="delKnob" />').text('×');      

this.cart
  .on('click', '.delKnob', function(){              
    var item = $(this).parent().find('[data-item]').data('item');
    $(this).detach();
    self.remove(item);
  });

DEMO