【问题标题】:JQuery .on("click") triggers "mouseover" on touch deviceJQuery .on("click") 在触摸设备上触发“鼠标悬停”
【发布时间】:2016-09-21 02:04:06
【问题描述】:

我在触摸设备上使用 JQuery 的 $.on("click", function(){}); 时遇到了不受欢迎的行为。这是我下面的代码:

代码:

$(".team").on("mouseover", teamMouseOver);
$(".team").on("mouseout", teamMouseOut);
$(".team").on("click", teamThumbClicked);

function teamMouseOver(event){
    console.log(event.type);
}

function teamMouseOut(event){
    // Do something
}

function teamThumbClicked(event){
    console.log("Clicked!");
}

问题:

使用上面的代码,在触摸设备上点击 .team 元素会同时触发两个侦听器,给我以下控制台日志:

mouseover
Clicked!

问题 为什么在触摸设备上触发mouseover?这不是我对没有鼠标的设备所期望的行为。这是一个错误吗?我应该使用什么事件,所以“鼠标悬停”只有在它是一个实际的鼠标指针进入时才会被触发?

我的 JQuery 版本是 2.2.4。

【问题讨论】:

  • 这是正确的行为。你想达到什么目的?我最近遇到了同样的问题(在移动“点击”上添加了不需要的类)并且能够使用 CSS 特异性解决这个问题:developer.mozilla.org/en-US/docs/Web/CSS/Specificity
  • 我在mouseover 上显示一个工具提示,并在click 上隐藏它。如果这两个事件同时触发,则工具提示将保持可见,因为您单击了它应该被隐藏。这就是为什么当设备没有鼠标时我不需要触发mouseover。我认为这就是 touch 事件的用途。 JQuery 这样做是为了模拟 :hover 效果吗?
  • @MarcoDelValle 你最终解决了这个问题吗?我正在尝试解决类似的错误。谢谢!
  • @unsingefou 我不记得了,因为那是一年多以前的事了,但我想如果"touchstart" 发生在"clicked" 之前,我禁用了"mouseover" 事件侦听器。这很复杂,但这是我发现的唯一一种允许同时具有鼠标和触摸输入的设备的方法。

标签: javascript jquery touch mouseevent touch-event


【解决方案1】:

我刚刚遇到了同样的问题,这就是我为解决问题所做的。

$('#myEl').on('click', myElClickEvent);

$('#myEl').on('mouseenter', myElMouseEnterEvent);

function myElClickEvent (event) {
   $(this).addClass('Clicked');
}

function myElMouseEnterEvent() {
    // Turn off events
    $('#myEl').off();

    // After 100 milliseconds cut on events, notice click event won't trigger
    setTimeout(function() {
       // .off() is used to prevent from adding multiple click events if the user hovers multiple elements too quickly.
       $('#myEl').off().on('click', myElClickEvent);             
       $('#myEl').off().on('mouseenter', myElMouseEnterEvent);
    }, 100);


   // Do some mouseenter stuff, whatever the reqs. are.
}

这就是我所做的,它适用于我的用例。希望这对将来的某人有所帮助。这个想法是关闭鼠标输入事件中的单击事件,然后在 100 毫秒后重新打开鼠标单击事件。这将防止两个事件在触​​摸时触发。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,也觉得我们不能分开这两个事件有点烦人。我解决这个问题的方法是添加 touchend 事件并让它首先标记它是一个触摸设备。由于其余事件将随之而来,因此我可以忽略它们或对它们执行其他操作,并且如果由非触摸设备触发,它们仍将运行。

    var touchEndDetected = false;
    var mouseOverDetected = false;
    
    $('#myEl').on('click mouseover touchend', function (e) {
        console.log('Event type: ' + e.type);
    
        if(mouseOverDetected) {
            console.log('Mouseover event has already run this before');
            touchEndDetected = false;
            mouseOverDetected = false;
            return;
        }
    
        if(touchEndDetected) {
            touchEndDetected = false;
            mouseOverDetected = true;
            console.log('Touchend event has already run this before');
            return;
        }
    
        if(e.type === 'touchend') {
            touchEndDetected = true;
            mouseOverDetected = false;
        }
    
        console.log('This code will only run once when touch');
    }
    

    【讨论】:

      【解决方案3】:

      在原始触摸事件上调用.preventDefault()

      API 链接实际上提供了答案。 https://developer.mozilla.org/en-US/docs/Web/API/Touch_events/Supporting_both_TouchEvent_and_MouseEvent#event_firing.

      在您的情况下,您正在使用 jQuery 的 .on() 函数,您可以向该函数发送多个事件(以空格分隔),因此您可以将 touchstart ontouchstart 添加到该字符串并调用 preventDeault() 对在您的处理程序函数中立即启动。

      $(".team").on("click touchstart", teamThumbClicked);
      
      // and later...
      
      function teamThumbClicked(event){
          event.preventDefault(); // prevent further mouse events from being dispatched
          console.log("Clicked!");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-17
        • 2023-04-07
        • 1970-01-01
        相关资源
        最近更新 更多