什么会导致点击事件多次触发?

时间:2016-09-16 21:46:32

标签: javascript jquery css

我有一个小的待办事项列表,我为练习。这是一个Fiddle ,我似乎无法弄清楚为什么切换添加和删除todo中的直通的类的click事件适用于某些项目,而不是其他项目。我检查了控制台,由于某些原因,那些不工作的,当点击时,会多次触发。如果有人可以给我一些指示,为什么会这样,我会非常感激。

// Toggle line-through todo
$('.todo-container').on('click', function(){
  $(this).toggleClass('line-through');
  console.log("fired")
})

1 个答案:

答案 0 :(得分:2)

就像Mike评论的那样,你在每个输入按键上再次为元素添加一个新的处理程序,而是使用event delegation

进一步解释:

当您添加如下所示的事件处理程序时,jQuery会查看DOM并将处理程序直接添加到具有 todo-container 类的任何元素。

$('.todo-container').on('click', function()...

$('.todo-container').click(function()...

一个重要的警告是,此只会将处理程序添加到页面上当前存在的元素。

当您意识到处理程序不能在新创建的(动态)元素上运行时,您会看到此结果。

不太明白为什么它不起作用,您将事件绑定移动到keyup的处理程序中,每次创建新元素时都有效地调用绑定。这个似乎起初工作但实际上是有缺陷的,因为再次将处理程序直接添加到具有todo-container类的任何元素。包括已经存在的元素有一个从前一次调用定义的处理程序。

修复一个,Event delegation(首选方法)

在下面的示例中,我们将绑定移回到keyup处理程序之外,并使用$('#todos').on('click', '.todo-container',将侦听器附加到'#todos'元素(始终存在于页面上)。然后,每当您在该元素内部单击时,它会检查您单击的子项是否具有“todo-container”类,如果是,则会触发您的代码。这是事件委托。这将捕获与选择器

匹配的任何动态元素上的事件
$(document).on('keypress', function(e) {
  // Add todo
  if (e.which === 13 && $('.input-field').val() != "") {
    $('#todos').prepend(todoTemplate);
    var todo = $('.todo-container');
    $('#todos').children().first().find(todo).html($('.input-field').val());
    $('.input-field').val("");
  }

})



// Remove todo
$('#todos').on('click', '.todo-container-delete', function() {
    $(this).parent().remove();
  })
  // Toggle line-through todo
$('#todos').on('click', '.todo-container', function() {
  $(this).toggleClass('line-through');
  console.log("hello")
})

使用:last

修复两个更具体的定位

如果您专门针对新添加的元素,您实际上可以将绑定留在keyup处理程序中:

$('#todos .todo-container:last').on('click', function(){

$('#todos .todo-container:last').click(function(){

修正三,(不是真的推荐但可能).off()

如果使用.off()从前面的元素中删除处理程序,然后再将其添加到所有元素,也可以将绑定保留在keyup处理程序中:

$('.todo-container').off().on('click', function(){

我会避免使用这种方法,因为如果你没有专门针对要删除的处理程序(请参阅文档说明),那么你将删除应用于该元素的所有处理程序,这肯定会让你失望路

相关问题