如何绑定'touchstart'和'click'事件但不回复两者?

时间:2011-08-10 22:56:05

标签: jquery click touchstart

我正在开发一个必须在各种设备上运行的移动网站。黑莓手机让我头疼的是。

我们需要同时支持键盘点击和触摸事件。

理想情况下,我只会使用:

$thing.click(function(){...})

但我们遇到的问题是这些黑莓设备中的一些从触摸到触发点击时会有非常烦人的延迟。

补救措施是使用touchstart:

$thing.bind('touchstart', function(event){...})

但是,如何绑定这两个事件,但只触发一个?我仍然需要键盘设备的click事件,但当然,如果我使用的是触控设备,则不希望点击事件触发。

一个额外的问题:无论如何都有这样做,并且还适用于甚至没有touchstart事件的浏览器?在研究这个问题时,看起来BlackBerry OS5不支持touchstart,因此还需要依赖该浏览器的点击事件。

附录:

也许更全面的问题是:

使用jQuery,是否可以/建议使用相同的绑定处理触摸交互和鼠标交互?

理想情况下,答案是肯定的。如果没有,我确实有一些选择:

1)我们使用WURFL获取设备信息,因此可以创建我们自己的设备矩阵。根据设备的不同,我们将使用touchstart或点击。

2)通过JS检测浏览器中的触摸支持(我需要对此进行更多研究,但看起来可行)。

然而,这仍然存在一个问题:支持BOTH的设备如何。我们支持的一些手机(即Nokias和黑莓手机)同时具有触摸屏键盘。所以这种方式让我完全回到原来的问题......有没有办法让某种方式同时允许两种方式?

36 个答案:

答案 0 :(得分:127)

更新:查看jQuery Pointer Events Polyfill项目,该项目允许您绑定到“指针”事件,而不是在鼠标和鼠标之间进行选择。触摸。


绑定到两者,但是制作一个标志,这样该函数每100ms左右才会触发一次。

var flag = false;
$thing.bind('touchstart click', function(){
  if (!flag) {
    flag = true;
    setTimeout(function(){ flag = false; }, 100);
    // do something
  }

  return false
});

答案 1 :(得分:71)

这是我“创建”的修复程序,它取出了GhostClick并实现了FastClick。尝试自己,让我们知道它是否适合您。

$(document).on('touchstart click', '.myBtn', function(event){
        if(event.handled === false) return
        event.stopPropagation();
        event.preventDefault();
        event.handled = true;

        // Do your magic here

});

答案 2 :(得分:48)

您可以尝试这样的事情:

var clickEventType=((document.ontouchstart!==null)?'click':'touchstart');
$("#mylink").bind(clickEventType, myClickHandler);

答案 3 :(得分:42)

通常这也适用:

$('#buttonId').on('touchstart click', function(e){
    e.stopPropagation(); e.preventDefault();
    //your code here

});

答案 4 :(得分:17)

只需在return false;事件函数末尾添加on("click touchstart")即可解决此问题。

$(this).on("click touchstart", function() {
  // Do things
  return false;
});

来自.on()

上的jQuery文档
  

从事件处理程序返回false会自动调用event.stopPropagation()event.preventDefault()。也可以为处理程序传递false值作为function(){ return false; }的简写。

答案 5 :(得分:10)

我必须做类似的事情。这是对我有用的简化版本。如果检测到触摸事件,请删除单击绑定。

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click');

  //your code here
});

在我的情况下,click事件被绑定到<a>元素,因此我不得不删除click绑定并重新绑定一个阻止<a>元素的默认操作的click事件。

$thing.on('touchstart click', function(event){
  if (event.type == "touchstart")
    $(this).off('click').on('click', function(e){ e.preventDefault(); });

  //your code here
});

答案 6 :(得分:7)

我通过以下方式取得了成功。

轻松鄙视......

$(this).on('touchstart click', function(e){
  e.preventDefault();
  //do your stuff here
});

答案 7 :(得分:4)

通常,您不希望混合默认触摸和非触摸(单击)API。一旦进入触摸世界,就更容易处理与触摸相关的功能。下面是一些伪代码可以达到你想要的效果。

如果您连接touchmove事件并跟踪位置,您可以在doTouchLogic函数中添加更多项目以检测手势等等。

var touchStartTime;
var touchStartLocation;
var touchEndTime;
var touchEndLocation;

$thing.bind('touchstart'), function() {
     var d = new Date();
     touchStartTime = d.getTime();
     touchStartLocation = mouse.location(x,y);
});

$thing.bind('touchend'), function() {
     var d = new Date();
     touchEndTime= d.getTime();
     touchEndLocation= mouse.location(x,y);
     doTouchLogic();
});

function doTouchLogic() {
     var distance = touchEndLocation - touchStartLocation;
     var duration = touchEndTime - touchStartTime;

     if (duration <= 100ms && distance <= 10px) {
          // Person tapped their finger (do click/tap stuff here)
     }
     if (duration > 100ms && distance <= 10px) {
          // Person pressed their finger (not a quick tap)
     }
     if (duration <= 100ms && distance > 10px) {
          // Person flicked their finger
     }
     if (duration > 100ms && distance > 10px) {
          // Person dragged their finger
     }
}

答案 8 :(得分:4)

我认为现在最好的做法是使用:

$('#object').on('touchend mouseup', function () { });
  

touchend

     

从触摸表面移除触摸点时会触发touchend事件。

     

touchend事件将触发任何鼠标事件。

           

mouseup

     

当鼠标指针悬停在元素上并且释放鼠标按钮时,mouseup事件将发送到元素。任何HTML元素都可以接收此事件。

     

mouseup事件将触发任何触摸事件。

示例

&#13;
&#13;
$('#click').on('mouseup', function () { alert('Event detected'); });
$('#touch').on('touchend', function () { alert('Event detected'); });
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="click">Click me</h1>
<h1 id="touch">Touch me</h1>
&#13;
&#13;
&#13;

编辑(2017)

从2017年开始,浏览器从Chrome开始,通过消除点击请求中点击事件产生的延迟,使点击事件.on("click")更兼容鼠标和触摸。

这导致得出的结论是,恢复使用单击事件将是最简单的解决方案。

我还没有进行任何跨浏览器测试,看看这是否合适。

答案 9 :(得分:3)

嗯......所有这些都非常复杂。

如果你有现代化的话,那就明白了。

ev = Modernizr.touch ? 'touchstart' : 'click';

$('#menu').on(ev, '[href="#open-menu"]', function(){
  //winning
});

答案 10 :(得分:3)

检查来自Google https://developers.google.com/mobile/articles/fast_buttons

的快速按钮和点击次数

答案 11 :(得分:2)

你可以尝试这样:

var clickEvent = (('ontouchstart' in document.documentElement)?'touchstart':'click');
$("#mylink").on(clickEvent, myClickHandler);

答案 12 :(得分:2)

我想出了记住ontouchstart是否被触发的想法。在这种情况下,我们在支持它的设备上,并且想要忽略onclick事件。由于ontouchstart应该始终在 onclick之前触发,我使用的是:

<script> touchAvailable = false; </script>
<button ontouchstart="touchAvailable=true; myFunction();" onclick="if(!touchAvailable) myFunction();">Button</button>

答案 13 :(得分:2)

仅出于文档目的,以下是我所做的最快/响应最快的桌面点击/点击移动解决方案,我能想到:

我将jQuery的on函数替换为修改后的函数,只要浏览器支持触摸事件,就用touchstart替换所有点击事件。

$.fn.extend({ _on: (function(){ return $.fn.on; })() });
$.fn.extend({
    on: (function(){
        var isTouchSupported = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
        return function( types, selector, data, fn, one ) {
            if (typeof types == 'string' && isTouchSupported && !(types.match(/touch/gi))) types = types.replace(/click/gi, 'touchstart');
            return this._on( types, selector, data, fn);
        };
    }()),
});

用法比以前完全相同,如:

$('#my-button').on('click', function(){ /* ... */ });

但它会在可用时使用touchstart,否则会点击。不需要任何延迟:D

答案 14 :(得分:2)

另一种实现更好维护的实施方案。但是,这种技术也会执行event.stopPropagation()。单击不会被点击100ms的任何其他元素。

var clickObject = {
    flag: false,
    isAlreadyClicked: function () {
        var wasClicked = clickObject.flag;
        clickObject.flag = true;
        setTimeout(function () { clickObject.flag = false; }, 100);
        return wasClicked;
    }
};

$("#myButton").bind("click touchstart", function (event) {
   if (!clickObject.isAlreadyClicked()) {
      ...
   }
}

答案 15 :(得分:1)

在我的情况下,这完美地运作:

jQuery(document).on('mouseup keydown touchend', function (event) {
var eventType = event.type;
if (eventType == 'touchend') {
    jQuery(this).off('mouseup');
}
});

主要的问题是,当我尝试使用点击鼠标时,触摸设备同时触发了点击和触摸,如果我使用点击关闭,某些功能在移动设备上根本不起作用。 click的问题在于,它是一个全局事件,可触发事件的其余部分,包括touchend。

答案 16 :(得分:1)

为我提供Mottie给出的最佳答案,我只是想让他的代码更可重复使用,所以这是我的贡献:

bindBtn ("#loginbutton",loginAction);

function bindBtn(element,action){

var flag = false;
$(element).bind('touchstart click', function(e) {
    e.preventDefault();
    if (!flag) {
        flag = true;
        setTimeout(function() {
            flag = false;
        }, 100);
        // do something
        action();
    }
    return false;
});

答案 17 :(得分:1)

这对我有用,移动设备同时监听两者,所以要防止一个,这是触摸事件。桌面只听老鼠。

 $btnUp.bind('touchstart mousedown',function(e){
     e.preventDefault();

     if (e.type === 'touchstart') {
         return;
     }

     var val = _step( _options.arrowStep );
               _evt('Button', [val, true]);
  });

答案 18 :(得分:0)

我找到的最好的方法是编写触摸事件并让该事件以编程方式调用正常的单击事件。这样您就拥有了所有正常的点击事件,然后您需要为所有触摸事件添加一个事件处理程序。对于您想要触摸的每个节点,只需添加“touchable”类即可调用触摸处理程序。使用Jquery,它可以通过一些逻辑来确保它是一个真正的触摸事件,而不是误报。

$("body").on("touchstart", ".touchable", function() { //make touchable  items fire like a click event
var d1 = new Date();
var n1 = d1.getTime();
setTimeout(function() {
    $(".touchable").on("touchend", function(event) {
        var d2 = new Date();
        var n2 = d2.getTime();
        if (n2 - n1 <= 300) {
            $(event.target).trigger("click"); //dont do the action here just call real click handler
        }
    });
}, 50)}).on("click", "#myelement", function() {
//all the behavior i originally wanted
});

答案 19 :(得分:0)

找到文件滚动移动差异(水平和垂直)touchstart和touchend,如果其中一个大于1像素,则移动而不是单击

var touchstartverscrollpos , touchstarthorscrollpos;


    $('body').on('touchstart','.thumbnail',function(e){

        touchstartverscrollpos = $(document).scrollTop();
        touchstarthorscrollpos = $(document).scrollLeft();


    });



    $('body').on('touchend','.thumbnail',function(e){


        var touchendverscrollpos = $(document).scrollTop();
        var touchendhorscrollpos = $(document).scrollLeft();

        var verdiff = touchendverscrollpos - touchstartverscrollpos;
        var hordiff = touchendhorscrollpos - touchstarthorscrollpos;


        if (Math.abs(verdiff) <1 && Math.abs(hordiff)<1){

// do you own function () here 



            e.stopImmediatePropagation();

            return false;
        }

    });

答案 20 :(得分:0)

<强> UDPATE:

我一直致力于为同一个函数使用click和touchend事件的实现,如果类型发生变化,该函数会有效地阻止事件。我的目标是拥有一个响应更快的应用程序界面 - 我希望减少事件开始到UI反馈循环的时间。

要使此实施有效,我们假设您已添加了所有相关事件,并点击了&#39;和&#39; touchend&#39;。如果两个事件都需要运行,但是它们的类型不同,这可以防止一个元素被剥夺事件冒泡。

这是一个基于API的轻量级实现,我为了演示目的进行了简化。它演示了如何在折叠元素上使用该功能。

var tv = {
    /**
     * @method eventValidator()
     * @desc responsible for validating event of the same type.
     * @param {Object} e - event object
     * @param {Object} element - element event cache
     * @param {Function} callback - callback to invoke for events of the same type origin
     * @param {Object} [context] - context to pass to callback function
     * @param {Array} [args] - arguments array to pass in with context. Requires context to be passed
     * @return {Object} - new event cache
     */
    eventValidator: function(e, element, callback, context, args){
        if(element && element.type && element.type !== e.type){
            e.stopPropagation();
            e.preventDefault();
            return tv.createEventCacheObj({}, true);
        } else {
            element = tv.createEventCacheObj(e);
            (typeof context === "object" ? callback.apply(context, args) : callback());
            return element;
        }
    },

    /**
     * @method createEventCacheObj()
     * @param {Object} event - event object
     * @param {String} [event.type] - event type
     * @param {Number} [event.timeStamp] - time of event in MS since load
     * @param {Boolean} [reset=false] - flag to reset the object
     * @returns {{type: *, time: string}}
     */
    createEventCacheObj: function (event, reset){
        if(typeof reset !== 'boolean') reset = false;
        return {
            type: !reset ? event.type : null,
            time: !reset ? (event.timeStamp).toFixed(2): null
        };
    }
};

// Here is where the magic happens
var eventCache = [];
var pos = 0;

var $collapses = document.getElementsByClassName('tv-collapse__heading');
    Array.prototype.forEach.call($collapses, function(ele){
        ele.addEventListener('click', toggleCollapse);
        ele.addEventListener('touchend', toggleCollapse);

        // Cache mechanism
        ele.setAttribute('data-event-cache', String(pos++));
    });

/**
 * @func toggleCollapse()
 * @param {Object} e - event object
 * @desc responsible for toggling the state of a collapse element
 */
function toggleCollapse(e){
    eventCache[pos] = tv.eventValidator(e, eventCache[pos], function(){
       // Any event which isn't blocked will run the callback and its content
       // the context and arguments of the anonymous function match the event function context and arguments (assuming they are passed using the last two parameters of tv.eventValidator)

    }, this, arguments);
}

原始答案:

这是一个响应,它是对Rafael Fragoso's回答的修改 - 纯JS。

&#13;
&#13;
(function(){
  
  button = document.getElementById('sayHi');
  
  button.addEventListener('touchstart', ohHai);
  button.addEventListener('click', ohHai);

  function ohHai(event){
    event.stopPropagation();
    event.preventDefault();
    console.log('ohHai is:', event.type);
  };
})();
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SO - Answer</title>
</head>
<body>
  <button id="sayHi">Anyone there?</button>
</body>
</html>
&#13;
&#13;
&#13;

运行以下代码片段并注意输出:

  • 电话
  • 平板
  • 平板电脑(桌面模式 - 如果适用)
  • 桌面
  • 桌面(触摸屏 - 如果适用)

关键是我们要阻止连续事件发射。移动浏览器会在触摸发生时尽力模拟点击。我希望我能找到一篇文章的链接,这篇文章说明了touchstart点击之后发生的所有事件。 (我正在寻找双击和点击实际射击之间300毫秒的延迟。)

触摸和鼠标设备

我使用Surface Pro和带触摸屏的Windows 10桌面进行了几项测试。我发现他们都触发了你想要的事件,touchstart触摸和点击触控板,鼠标和造型师。有趣的是,接近但不在按钮上的触摸事件会在没有触摸事件的情况下触发点击事件。看起来Windows 10中的内置功能会查找半径内最近的节点,如果找到一个节点,它将触发基于鼠标的事件。

相同类型的多个事件

如果元素上有两个相同类型的事件,则阻止事件冒泡可能会阻止其中一个事件触发。使用某种缓存有两种不同的方法来处理它。我最初的想法是修改事件对象,但我们得到一个参考,所以我认为缓存解决方案就足够了。

答案 21 :(得分:0)

这是一个简单的方法:

// A very simple fast click implementation
$thing.on('click touchstart', function(e) {
  if (!$(document).data('trigger')) $(document).data('trigger', e.type);
  if (e.type===$(document).data('trigger')) {
    // Do your stuff here
  }
});

您基本上将触发的第一个事件类型保存在附加到根文档的jQuery数据对象中的“trigger”属性中,并且仅在事件类型等于“trigger”中的值时执行。在触摸设备上,事件链可能是“触摸启动”,然后是“点击”;但是,“click”处理程序不会被执行,因为“click”与“trigger”(“touchstart”)中保存的初始事件类型不匹配。

我认为这是一个安全的假设是,您的智能手机不会自动从触摸设备更改为鼠标设备,否则点击将无法注册,因为“触发”事件类型仅为每页加载一次保存,“click”永远不会匹配“touchstart”。

这是您可以使用的编码器(尝试点击触摸设备上的按钮 - 应该没有点击延迟):http://codepen.io/thdoan/pen/xVVrOZ

我还将它实现为一个简单的jQuery插件,它还通过传递选择器字符串来支持jQuery的后代过滤:

// A very simple fast click plugin
// Syntax: .fastClick([selector,] handler)
$.fn.fastClick = function(arg1, arg2) {
  var selector, handler;
  switch (typeof arg1) {
    case 'function':
      selector = null;
      handler = arg1;
      break;
    case 'string':
      selector = arg1;
      if (typeof arg2==='function') handler = arg2;
      else return;
      break;
    default:
      return;
  }
  this.on('click touchstart', selector, function(e) {
    if (!$(document).data('trigger')) $(document).data('trigger', e.type);
    if (e.type===$(document).data('trigger')) handler.apply(this, arguments);
  });
};

Codepen:http://codepen.io/thdoan/pen/GZrBdo/

答案 22 :(得分:0)

我给出了一个答案there,并用jsfiddle进行了演示。 您可以检查其他设备并进行报告。

基本上,我使用一种带有某些功能的事件锁:

/*
 * Event lock functions
 * ====================
 */
function getEventLock(evt, key){
   if(typeof(eventLock[key]) == 'undefined'){
      eventLock[key] = {};
      eventLock[key].primary = evt.type;
      return true;
   }
   if(evt.type == eventLock[key].primary)
      return true;
   else
      return false;
}

function primaryEventLock(evt, key){
   eventLock[key].primary = evt.type;
}

然后,在事件处理程序中,我从对锁的请求开始:

/*
 * Event handlers
 * ==============
 */
$("#add").on("touchstart mousedown", addStart);
$("#add").on("touchend mouseup", addEnd);
function addStart(evt){
   // race condition between 'mousedown' and 'touchstart'
   if(!getEventLock(evt, 'add'))
      return;

   // some logic
   now = new Date().getTime();
   press = -defaults.pressDelay;
   task();

   // enable event lock and(?) event repetition
   pids.add = setTimeout(closure, defaults.pressDelay);

   function closure(){
        // some logic(?): comment out to disable repetition
      task();

      // set primary input device
      primaryEventLock(evt, 'add');

      // enable event repetition
      pids.add = setTimeout(closure, defaults.pressDelay);
   }
}
function addEnd(evt){
      clearTimeout(pids.add);
}

我必须强调,问题不只是在一个事件上做出回应,而是对这两项做出回应。

最后,在 jsfiddle 处,有一个更新版本的链接,在该版本中,我通过在事件开始和结束处理程序以及对事件锁库添加一个简单的调用来对现有代码产生最小的影响2个范围变量eventLockeventLockDelay

答案 23 :(得分:0)

这里没有提到,但是您可能想要查看以下链接:https://joshtronic.com/2015/04/19/handling-click-and-touch-events-on-the-same-element/

要回顾一下后代,您可以简单地检查设备是否为触摸屏,而仅分配给相关事件,而不是尝试分配给两个处理程序然后对结果进行排序。观察:

var clickEvent = (function() {
  if ('ontouchstart' in document.documentElement === true)
    return 'touchstart';
  else
    return 'click';
})();

// and assign thusly:

el.addEventListener( clickEvent, function( e ){ 
    // things and stuff
});

我正在使用它来绑定事件,以便可以在同时处理两次的touchstartclick事件的触摸屏上进行测试,并在只能听到{{1 }}

该链接的作者提到的一个问题是触摸屏笔记本电脑,旨在处理这两种情况:

  

我了解到我没有考虑的第三种设备,即触摸屏笔记本电脑。这是一款同时支持触摸和点击事件的混合设备。绑定一个事件意味着仅支持该事件。这是否意味着拥有触摸屏和鼠标的人将必须明确触摸,因为那是我正在处理的唯一事件?

     

绑定clicktouchstart似乎是处理这些混合设备的理想选择。为了防止事件触发两次,我在回调函数中添加了clicke.stopPropagation()e.preventDefault()阻止了事件“冒泡”给父母,但也阻止了第二事件的发生。我将e.stopPropagation()列为“以防万一”,但似乎可以省略。

答案 24 :(得分:0)

尝试使用Virtual Mouse (vmouse) Bindings中的jQuery Mobile。 它的虚拟事件尤其适用于您的情况:

$thing.on('vclick', function(event){ ... });

http://api.jquerymobile.com/vclick/

浏览器支持列表:http://jquerymobile.com/browser-support/1.4/

答案 25 :(得分:0)

编辑:我之前的回答(基于此主题中的答案)不适合我。我想要一个子菜单来扩展鼠标输入或触摸点击,并在鼠标离开或其他触摸点击时折叠。由于鼠标事件通常在触摸事件之后被触发,因此编写同时支持触摸屏和鼠标输入的事件侦听器是很棘手的。

jQuery插件:Touch Or Mouse

我最终编写了一个名为&#34; Touch Or Mouse&#34;的jQuery插件。 (897字节缩小)可以检测事件是否被触摸屏或鼠标调用(没有测试触摸支持!)。这样可以同时支持触摸屏和鼠标 并完全分离它们的事件。

通过这种方式,OP可以使用touchstarttouchend来快速响应触摸点击,并click用于鼠标调用的点击次数。

示范

首先要做的是ie。身体元素跟踪触摸事件:

$(document.body).touchOrMouse('init');

鼠标事件我们以默认方式绑定到元素,并通过调用$body.touchOrMouse('get', e)我们可以找出事件是否是由触摸屏或鼠标调用。

$('.link').click(function(e) {
  var touchOrMouse = $(document.body).touchOrMouse('get', e);

  if (touchOrMouse === 'touch') {
    // Handle touch click.
  }
  else if (touchOrMouse === 'mouse') {
    // Handle mouse click.
  }
}

请参阅http://jsfiddle.net/lmeurs/uo4069nh处的插件。

解释

      
  1. 此插件需要调用ie。跟踪touchstarttouchend事件的body元素,这样就不必在触发器元素(即链接或按钮)上触发touchend事件。在这两个触摸事件之间,此插件会考虑通过触摸调用任何鼠标事件。
  2.   
  3. 鼠标事件仅在touchend之后触发,当ghostEventDelaytouchend(选项,默认为1000毫秒)内触发鼠标事件时,此插件会将鼠标事件视为被触摸调用。
  4.   
  5. 使用触摸屏单击元素时,元素将获得:active状态。仅在元素通过ie丢失此状态后才会触发mouseleave事件。点击另一个元素。因为在mouseenter事件被触发后,这可能是秒(或分钟!),此插件会跟踪元素的最后mouseenter事件:如果最后mouseenter事件通过触摸调用,以下mouseleave事件也被视为通过触摸调用。

答案 26 :(得分:0)

我正在尝试这个并且到目前为止它的确有效(但我只是在Android / Phonegap上这么警告)

  function filterEvent( ob, ev ) {
      if (ev.type == "touchstart") {
          ob.off('click').on('click', function(e){ e.preventDefault(); });
      }
  }
  $('#keypad').on('touchstart click', '.number, .dot', function(event) {
      filterEvent( $('#keypad'), event );
      console.log( event.type );  // debugging only
           ... finish handling touch events...
  }

我不喜欢这样一个事实:我会在每次触摸时重新绑定处理程序,但所有被认为触及的事情都不会经常发生(在计算机时间内!)

我有一大堆处理程序,比如#键盘和#39;所以我有一个简单的功能,让我可以在没有太多代码的情况下处理问题,这就是我这样做的原因。

答案 27 :(得分:0)

对于简单的功能,只需识别触摸或单击我使用以下代码:

var element = $("#element");

element.click(function(e)
{
  if(e.target.ontouchstart !== undefined)
  {
    console.log( "touch" );
    return;
  }
  console.log( "no touch" );
});

如果定义了touchstart事件,则返回“touch”,否则返回“no touch”。就像我说的那样,这是一个简单的点击/点击事件方法。

答案 28 :(得分:0)

如果您使用的是jQuery,以下内容对我来说效果很好:

var callback; // Initialize this to the function which needs to be called

$(target).on("click touchstart", selector, (function (func){
    var timer = 0;
    return function(e){
        if ($.now() - timer < 500) return false;
        timer = $.now();
        func(e);
    }
})(callback));

其他解决方案也很好但是我在循环中绑定了多个事件,并且需要自调用函数来创建适当的闭包。此外,我不想禁用绑定,因为我希望它可以在下一次单击/ touchstart时调用。

可能会帮助处于类似情况的人!

答案 29 :(得分:0)

为什么不使用jQuery Event API?

http://learn.jquery.com/events/event-extensions/

我成功地使用了这个简单的事件。它干净,命名空间和灵活性足以改进。

var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
var eventType = isMobile ? "touchstart" : "click";

jQuery.event.special.touchclick = {
  bindType: eventType,
  delegateType: eventType
};

答案 30 :(得分:0)

利用点击将始终跟随触摸事件的事实,这就是我在不必使用超时或全局标记的情况下摆脱“鬼点击”的行为。

$('#buttonId').on('touchstart click', function(event){
    if ($(this).data("already")) {
        $(this).data("already", false);
        return false;
    } else if (event.type == "touchstart") {
        $(this).data("already", true);
    }
    //your code here
});

基本上每当ontouchstart事件触发该元素时,标记为一个集合,然后在点击到来时随后删除(并忽略)。

答案 31 :(得分:0)

分配到事件'touchstart mousedown''touchend mouseup'以避免使用click产生不良副作用可能会有效。

答案 32 :(得分:0)

尝试解决此问题时需要考虑很多事项。大多数解决方案要么打破滚动,要么不能正确处理鬼点击事件。

有关完整解决方案,请参阅https://developers.google.com/mobile/articles/fast_buttons

注意:您无法在每个元素的基础上处理鬼点击事件。屏幕位置会触发延迟点击,因此如果您的触摸事件以某种方式修改了页面,则点击事件将被发送到新版本的页面。

答案 33 :(得分:0)

我也在开发Android / iPad网络应用程序,似乎只使用“touchmove”足以“移动组件”(不需要touchstart)。 通过禁用touchstart,您可以使用.click();来自jQuery。它实际上正在工作,因为它没有被touchstart重载。

最后,你可以binb .live(“touchstart”,function(e){e.stopPropagation();});要求touchstart事件停止传播,客厅点击()以触发。

它对我有用。

答案 34 :(得分:-1)

我不确定这是否适用于所有浏览器和设备。 我使用谷歌浏览器和Safari iOS进行了测试。

$thing.on('click || touchend', function(e){

});

OR opperand应该只触发第一个事件(在应该点击的桌面上和应该是touchend的iPhone上)。

答案 35 :(得分:-2)

您可以使用计数器代替超时:

var count = 0;
$thing.bind('touchstart click', function(){
  count++;
  if (count %2 == 0) { //count 2% gives the remaining counts when devided by 2
    // do something
  }

  return false
});