on click事件在移动端点击无效bug
发布时间:2017-08-10, 10:39:43 分类:HTML | 编辑 off 网址 | 辅助
图集1/2
正文 443字数 1,961,705阅读
关于on点击事件在ios中失效的问题IPhone中H5页面用on绑定click无效的解决方法
关于jquery中on绑定click事件在苹果手机失效的问题
如果不用必须用click,则换成touch自然不存在本文的bug。
当用如下方法绑定click事件时,
$(document).on('click','selector',function(){
});
Run code
Cut to clipboard
发现在PC各种浏览器,以及移动端模拟器上都是可以正常调试的,但是在ios的微信端访问或浏览器访问均有不同程度的无效情况,
解决办法如下:
第一种方法:解决的方法很巧妙,就是给需要绑定事件的元素添加一个css
cursor: pointer;
Run code
Cut to clipboard
selector {
cursor:pointer;
}
Run code
Cut to clipboard
第二种方法:把document换成selector的父元素,前提是父元素不是由JS生成的。
(支付宝)给作者钱财以资鼓励 (微信)→
有过 13 条评论 »
在手机上(iphone)点击按钮的时候,屏幕总会闪动一下,这让页面看起来很不友好也不流畅。解决方案加了一句css就解决了:
-webkit-tap-highlight-color:rgba(0,0,0,0)
//webkit是苹果浏览器引擎,tap点击,highlight背景高亮,color颜色,颜色用数值调节。
原因如下:
在移动端上,有事件监听的元素被点击的时候会被高亮显示,而-webkit-tap-highlight-color属性会在当用户点击iOS的Safari浏览器中的链接或JavaScript的可点击的元素时,覆盖显示的高亮颜色。
该属性可以只设置透明度。如果未设置透明度,iOS Safari使用默认的透明度。当透明度设为0,则会禁用此属性;当透明度设为1,元素在点击时不可见。
a{-webkit-tap-highlight-color:rgba(255,0,0,0);outline:none;}
ios微信点击超链接,去掉半透明黑色框效果
iOS微信点击超链接或是图片超链接,总是弹出一层黑色遮罩层,在a标签上添加style='-webkit-tap-highlight-color:rgba(255,0,0,0);'即可
<style> .next_button{ cursor:pointer } </style> <div class="button"> <div class=" next_button button_left btn_red" style="width: 345px;"> 下一步 </div> </div> <script> $(document).on("click",".next_button",function(){ alert(); }); </script>
使用苹果手机访问的时候,发现了一个坑爹的问题,如论如何点击“下一步”,都没有任何反应,可是在安卓和各种模拟器中一切正常。后来经过查找资料才知道,苹果有这么个设置:
对于点击的对象,拥有cursor:pointer这个样式的设置,也就是说,鼠标放上去,能够出现“手”型的图标才被认作可以使用点击事件,
$(document).on("click",function(){})
试过很多办法,在元素生成后 再绑定事件,把click改成touch事件,都没有用,最后好不容易百度到了解决办法
解决的方法很巧妙,就是给需要绑定事件的元素添加一个css
cursor: pointer
selector { cursor:pointer }
<script> $(document).on("touchstart",function(){console.log(‘22222‘)}) </script>
<script> $(selector).click(function(){console.log(‘1111‘)}) </script>
因为移动端click事件会比touchstart事件慢几拍
移动设备某个元素上事件执行顺序是:
touchstart touchmove touchend click{mousedown->mousemove->mouseup}
click事件在移动设备上虽然会识别但却是最后一个执行的,所以如果不把click事件换成touchstart事件的话,就可能造成延时导致交互上也慢了几拍
所以在移动端最好把click事件换成touchstart事件。
那么如何添加事件比较简单呢.
于是乎有了以下这种写法:
var handle = function (e) { e.preventDefault(); // 阻止浏览器默认行为 alert('fuck world'); } $('body').on(‘touchstart mousedown’, handle );
这样在pc端浏览器上面alert只执行一次,触发的事件是mousedown
在ios设备safari浏览器上面alert也只执行一次,触发的事件是touchstart
为什么只执行一次?
秘密在于当执行的是touchstart后,preventDefault掉了后面的click就不执行了,“非常完美”.
^_^! 一如既往的android设备蛋疼是必须的,测试发现除qq浏览器外其它浏览器都会alert两次
也就是说touchstart和mousedown的handle函数都执行了, 似乎是e.preventDefault()没有起作用。具体原因不明...
因为要兼容,所以就没办法了只能通过判断是否支持touch事件来分别添加事件了..
那就扩展一个jquery方法插件吧仿一个on方法的插件方法比如名称为quickOn,
;(function(){ var isTouch = ('ontouchstart' in document.documentElement) ? 'touchstart' : 'click'; if(!$.fn.quickOn){ $.fn.quickOn= function(){ arguments[0] = (arguments[0] === 'click') ? isTouch: arguments[0]; return $.fn.on.apply(this, arguments); }; } })();
quickOn虽然名字尴尬了一点,但是能用,例如:
$('body').quickOn('click', function(){ alert('fuck world') ; })
额。。后来想想,为什么不直接重载jquery的on方法呢??
来吧,试试
;(function(){ var isTouch = ('ontouchstart' in document.documentElement) ? 'touchstart' : 'click', _on = $.fn.on; $.fn.on = function(){ arguments[0] = (arguments[0] === 'click') ? isTouch: arguments[0]; return _on.apply(this, arguments); }; })();
这样暴力的来那么一下后,mmm....,on方法还是原来的用法,但如果你on的是click事件,那么在移动平台上会被替换成touchstart以迅速响应操作。
将其转成A标签即可。
$(document).on("click",'.class',function(){……});相当于$('.class').live("click",function(){……});
js生成的元素绑定事件必须使用live,但新版的jq,已经淘汰了live,可以用on方法代替,但必须注意写法。
<script> window.alert = function(name){ var iframe = document.createElement("IFRAME"); iframe.style.display="none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); window.frames[0].window.alert(name); iframe.parentNode.removeChild(iframe); } </script>
重写alert方法,去掉地址显示 //重写alert方法,去掉地址显示 window.alert = function(name){ var iframe = document.createElement("IFRAME"); iframe.style.display="none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); window.frames[0].window.alert(name); iframe.parentNode.removeChild(iframe); } //重写confirm方法,去掉地址显示 window.confirm = function(name){ var iframe = document.createElement("IFRAME"); iframe.style.display="none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); var result = window.frames[0].window.confirm(name); iframe.parentNode.removeChild(iframe); return result; }
ios移动端(H5)alert/confirm提示信息去除网址(URL)
在android中 有问题,过滤android var browser={ versions:function(){ var u = navigator.userAgent, app = navigator.appVersion; return { trident: u.indexOf('Trident') > -1, //IE内核 presto: u.indexOf('Presto') > -1, //opera内核 webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核 gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,//火狐内核 mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端 ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端 android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器 iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器 iPad: u.indexOf('iPad') > -1, //是否iPad webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部 }; }(), language:(navigator.browserLanguage || navigator.language).toLowerCase() } if(browser.versions.ios){ window.alert = function(name){ var iframe = document.createElement("IFRAME"); iframe.style.display="none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); window.frames[0].window.alert(name); iframe.parentNode.removeChild(iframe); }; window.confirm = function (message) { var iframe = document.createElement("IFRAME"); iframe.style.display = "none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); var alertFrame = window.frames[0]; var result = alertFrame.window.confirm(message); iframe.parentNode.removeChild(iframe); return result; }; }
<script> window.alert = function(name){ var iframe = document.createElement("IFRAME"); iframe.style.display="none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); window.frames[0].window.alert(name); iframe.parentNode.removeChild(iframe); } window.confirm = function (message) { var iframe = document.createElement("IFRAME"); iframe.style.display = "none"; iframe.setAttribute("src", 'data:text/plain,'); document.documentElement.appendChild(iframe); var alertFrame = window.frames[0]; var result = alertFrame.window.confirm(message); iframe.parentNode.removeChild(iframe); return result; }; </script>
touchstart:触摸开始的时候触发 touchmove:手指在屏幕上滑动的时候触发 touchend:触摸结束的时候触发
而每个触摸事件都包括了三个触摸列表,每个列表里包含了对应的一系列触摸点(用来实现多点触控):
touches:当前位于屏幕上的所有手指的列表。 targetTouches:位于当前DOM元素上手指的列表。 changedTouches:涉及当前事件手指的列表。
每个触摸点由包含了如下触摸信息(常用):
identifier:一个数值,唯一标识触摸会话(touch session)中的当前手指。一般为从0开始的流水号(android4.1,uc) target:DOM元素,是动作所针对的目标。 pageX/pageX/clientX/clientY/screenX/screenY:一个数值,动作在屏幕上发生的位置(page包含滚动距离,client不包含滚动距离,screen则以屏幕为基准)。 radiusX/radiusY/rotationAngle:画出大约相当于手指形状的椭圆形,分别为椭圆形的两个半径和旋转角度。
初步测试浏览器不支持,好在功能不常用,欢迎大家反馈。
var obj = document.getElementByIdx_x('id'); obj.addEventListener('touchmove', function(event) { // 如果这个元素的位置内只有一个手指的话 if (event.targetTouches.length == 1) { event.preventDefault();// 阻止浏览器默认事件,重要 var touch = event.targetTouches[0]; // 把元素放在手指所在的位置 obj.style.left = touch.pageX-50 + 'px'; obj.style.top = touch.pageY-50 + 'px'; } }, false);
删除onclick属性:$(“a”).removeAttr(“onclick”); 设置onclick属性:$(“a”).attr(“onclick”,”test();”);