【问题标题】:Click event fired twice on touch device点击事件在触摸设备上触发两次
【发布时间】:2019-10-21 14:46:11
【问题描述】:

我在sortable div 中有一个复选框,其中点击或更改事件在触摸设备上触发了两次,但在桌面上没有触发(也没有在 Firefox 开发工具上模拟触摸),原因不明。不想要的效果是复选框连续切换两次,使其保持原始状态。我提到 div 是可排序的,因为当它们不再可排序时,复选框工作得很好。以下是相关部分:

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

我不知道为什么可排序小部件会触发两次点击事件。

我试图处理这个问题没有成功:

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

// 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') 检查了绑定到输入的任何有问题的事件,但除了引导工具提示(鼠标悬停和鼠标悬停事件)以及更改事件之外,没有其他问题。

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

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

【问题讨论】:

  • 您使用的是哪种触控设备?
  • @Buisson 只是我的 Android 手机,但一些用户在“移动”上使用我们的网站时报告了这个问题(我没有被告知具体是哪种触摸设备)
  • 也许你已经为这个复选框添加了两个点击监听器?
  • @Buisson 并没有这样显示:$._data($sortable[0], 'events') 仅显示input[type="checkbox"] 选择器的单击事件。
  • 可能是因为,你的 sortable 和 checkbox 都触发了点击事件,

标签: javascript jquery


【解决方案1】:

尝试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
  }
});

【讨论】:

  • touchend 显然没有被触发
  • 首先尝试 'touchend touchcancel',如果这不起作用,请使用 addEventListener 将 touchend 事件添加到您的 $sortable。
  • 也没有被解雇。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多