同时使用onclick和ontouchstart

10

我在移动端视图上有一个ontouchstart事件被触发,它与以下内容相关:

function mobileLinksShow() {
    document.querySelector('.mobile-head-bar-links').classList.toggle('mobile-head-bar-links-transition');
}

当我在我的设备上(iPhone 5)点击按钮时,它会切换两次,因此它先扩展再收缩。这是因为onclick和ontouchstart同时触发。移除onclick可以解决移动设备上的问题,但桌面浏览器现在显然无法工作,是否有一种方法可以在移动设备上禁用onclick?

<span class='mobile-head-bar-left' ontouchstart='mobileLinksShow()' onclick='mobileLinksShow()' ><i class="fa fa-bars"></i></span>

CSS:

.mobile-head-bar-links {
    height: 0;
    overflow: hidden;
    background-color: #F76845;
    transition: .5s ease;
    -webkit-transition: .5s ease;
}

.mobile-head-bar-links-transition {
    height: 7em;
}

注意:我不想使用jQuery。

6个回答

6

通过测试浏览器类型并相应地删除onclick,找到了一个解决方法:

function removeMobileOnclick() {
    if(isMobile()) {
        document.querySelector('.mobile-head-bar-left').onclick  = '';
    }
}

function isMobile() {
    if (navigator.userAgent.match(/Android/i)
            || navigator.userAgent.match(/iPhone/i)
            || navigator.userAgent.match(/iPad/i)
            || navigator.userAgent.match(/iPod/i)
            || navigator.userAgent.match(/BlackBerry/i)
            || navigator.userAgent.match(/Windows Phone/i)
            || navigator.userAgent.match(/Opera Mini/i)
            || navigator.userAgent.match(/IEMobile/i)
            ) {
        return true;
    }
}
window.addEventListener('load', removeMobileOnclick);

这样可以同时使用 onclickontouchstart 而不会互相干扰。

检测移动设备中获取的isMobile函数,将webOS部分删除,因为它会将桌面浏览器视为移动设备。


3
由于触摸设备不仅限于手机(在2014年也不是如此),因此这种方法不好。 - Konstantin

6

我刚想到一个想法,就是记住是否触发了ontouchstart事件。在这种情况下,我们正在使用支持它的设备,并希望忽略onclick事件。由于ontouchstart应该始终在onclick之前被触发,所以我使用以下代码:

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


3
你可以将一个函数绑定到ontouchstart事件上,这个函数会调用与onclick绑定的任何内容,但是会阻止默认行为,以免触发onclick事件。
然后你可以轻松地将这个ontouchstart事件复制粘贴到所有使用onclick的地方。
<span class='mobile-head-bar-left' ontouchstart='touch_start(event)' onclick='mobileLinksShow()' ><i class="fa fa-bars"></i></span>

<script>
function touch_start(e){
  e.preventDefault();
  e.target.onclick();
}
</script>

在Chrome v65中无法工作:https://www.chromestatus.com/features/5093566007214080 - Raine Revere

0

对于触摸屏笔记本电脑(其中“点击”可能来自触摸或鼠标)等情况,此方法仍然存在问题。在某些移动设备上也存在问题,例如,点击不是来自触摸(例如,连接的或蓝牙键盘上的Enter键)。

正确的解决方案是使用preventDefault正确标记触摸事件,然后不会生成任何点击事件。例如:

function mobileLinksShow(event) {
  document.querySelector('.mobile-head-bar-links').classList.toggle('mobile-head-bar-links-transition');
  event.preventDefault();
}

详情请参见http://www.html5rocks.com/en/mobile/touchandmouse/


0
你可以这样写:
var called = false;
function mobileLinksShow() {
    if(!called)
        document.querySelector('.mobile-head-bar-links').classList.toggle('mobile-head-bar-links-transition');
        called = true;
    }
}

但是:如果您使用此代码,该函数只能被调用一次,即使您点击span两次。


0
在编程中,触摸事件使用e.preventDefault()默认情况下是不起作用的(从chrome 56开始)
您可以通过设置选项{{link2:{ passive: false }}}来手动让它工作。
document.querySelector('mobile-head-bar-left')
  .addEventListener(
    'touchstart',
    function(e) {
      // do something
      e.preventDefault()
    },
    { passive: false }
  )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接