点击事件在触摸设备上触发了两次

时间:2019-10-21 14:46:11

标签: javascript jquery

我在sortable div中有一个复选框,由于某些晦涩的原因,单击或更改事件在触摸设备上触发两次,但在台式机上(而不是在Firefox开发工具上模拟触摸)触发两次。不利的影响是,该复选框连续两次被切换为原始状态。我提到div是可排序的,因为当它们不再可排序时,此复选框就可以正常工作。这是相关的部分:

$sortable.sortable({
    items: '.sortable',
    cancel: 'input,textarea,button,select,option'
});

我不知道为什么可排序的小部件会使click事件被触发两次。

我尝试解决此问题失败:

我尝试禁用切换复选框和手动设置其值的默认行为。但是由于某种原因,该复选框将不会被选中/取消选中。如果我通过控制台执行此操作,那么它会起作用:

// same with the "change" event
// the reason the event is bound to $sortable rather than the inputs themselves is that 
// new sortable divs are added dynamically so otherwise they wouldn't have the event bound to them
$sortable.on('click', 'input[type="checkbox"]', function (e) {
  e.stopImmediatePropagation();
  // this does disable the default behaviour of checking/unchecking the box
  e.preventDefault();
  const $this = $(this);
  // this doesn't check/uncheck the box at all, but setting a global variable to $this and doing it via console does work
  $this.prop('checked', !$this.prop('checked'));
});

我已经尝试过使用标志的更典型方法,但是似乎存在一些竞争条件(或之所以调用它,是因为如果我没记错的话,js是单线程的),并且该函数无论如何都会运行两次:

let checked = false;
$sortable.on('click', 'input[type="checkbox"]', function() {
  if (checked) return;
  // this is output twice, which is not what we are after
  console.log('running');
  checked = true;
  // here ideally we would set the value of the checkbox
  checked = false;
});

我已经使用$._data($checkboxes[0], 'events')检查了绑定到输入的任何有问题的事件,但除了引导工具提示(鼠标悬停和mouseout事件)之外,当然,更改事件也没有其他问题。

编辑:基本上,当您在div或其子级中的任意位置单击时,可排序小部件似乎会产生一个单独的click事件。这就是点击/更改被两次触发的原因。

我的问题是:我如何区分事件的发起者,以便如果它是可排序的插件,则可以忽略该事件,而如果它是侦听器,则设置复选框会更改其事件值(并且在实际选中此复选框时执行其他可能要执行的其他操作)?

1 个答案:

答案 0 :(得分:0)

尝试touchend,如果它也适用于点击,请使用以下方法,否则将其

分开
$sortable.on("touchend click", 'input[type="checkbox"]', function(e) {
    if(e.type == 'touchend'){
        $(this).off('click');
        // your function
    }
});

否则都尝试

let checked = false;
$sortable.on("touchend click", 'input[type="checkbox"]', function(e) {
   if(e.type == "touchend") {
    checked = true;
    // your function
  }
  else if(e.type == "click" && !checked ) {
    // your function
  }
});