如何在排序后保留事件侦听器?

时间:2016-10-24 16:57:54

标签: javascript jquery

我正在创建DOM元素,然后使用这些DOM元素创建一个JQuery对象数组。在对JQuery对象进行排序并重新附加它们之后,click事件侦听器就消失了。有没有办法保留点击监听器?

for(var i=0; i<5; i++){
    var div = $('<div>',{
    id: i+"div",
    class: 'list-item '+i,
    html: "Item #"+i
  });
  div.data('i',i);
  $('.news-layout-1').append(div);
  div.on('click',function(){
    alert($(this).data('i'));
  }); 
}

$('.button').on('click',function(){
    var items = [];
  $('.news-layout-1').find('.list-item').each(function(index, item){
    items.push(item);
  });

  items = items.sort(function(a,b){
    var textA = $(a).html().toUpperCase();
    var textB = $(b).html().toUpperCase();
    return (textA > textB) ? -1 : (textA < textB) ? 1 : 0;
  });

  $('.news-layout-1').html('');

  for(var i=0; i<items.length; i++){
    $('.news-layout-1').append(items[i]);
  }
});

http://jsfiddle.net/bhav4co6/5/

2 个答案:

答案 0 :(得分:4)

您正在清除HTML,有效地从DOM中删除元素,并且它们只是保存在内存中,它们会丢失所有相关的数据和事件。

当你执行.empty()时,jQuery还在内部使用.html("")来确保删除元素,数据和事件监听器。

如果您只是删除该行

$('.news-layout-1').html('');

你很好,因为元素只会被移动,并保留事件监听器

&#13;
&#13;
for (var i = 0; i < 5; i++) {
    var div = $('<div>', {
        id: i + "div",
        class: 'list-item ' + i,
        html: "Item #" + i
    });
    div.data('i', i);
    $('.news-layout-1').append(div);
    div.on('click', function() {
        alert($(this).data('i'));
    });
}

$('.button').on('click', function() {
    var items = [];
    $('.news-layout-1').find('.list-item').each(function(index, item) {
        items.push(item);
    });

    items = items.sort(function(a, b) {
        var textA = $(a).html().toUpperCase();
        var textB = $(b).html().toUpperCase();
        return (textA > textB) ? -1 : (textA < textB) ? 1 : 0;
    });

    for (var i = 0; i < items.length; i++) {
        $('.news-layout-1').append(items[i]);
    }
});
&#13;
.list-item { cursor: pointer }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="news-layout-1">
</div>
<a href="#" class="button btn">
  Sort
</a>
&#13;
&#13;
&#13;

作为旁注,不需要添加数组或循环,你可以这样做

$('.button').on('click', function() {
    $('.news-layout-1 .list-item').sort(function(a, b) {
        var textA = $(a).html().toUpperCase();
        var textB = $(b).html().toUpperCase();
        return (textA > textB) ? -1 : (textA < textB) ? 1 : 0;
    }).appendTo('.news-layout-1');
});

答案 1 :(得分:2)

您可以委派事件,而不是将它们附加到for循环中。

当触发单击操作时,事件会冒泡到与单击处理程序关联的父元素(在本例中为body元素)。然后,您可以使用e.target获取发生点击的确切li

  $('body').on('click', '.list-item', function(e) {
         alert($(e.target).data('i'));
    });

    for (var i = 0; i < 5; i++) {
        var div = $('<div>', {
           id: i + "div",
           class: 'list-item ' + i,
           html: "Item #" + i
        });
        div.data('i', i);
        $('.news-layout-1').append(div);

       // move the click event out of the for loop
    }
相关问题