如何修复移动微信浏览器 touchend上 touchend 事件不触发的bug

移动端click事件延迟300ms到底是怎么回事,该如何解决? - 小媒体
移动端click事件延迟300ms到底是怎么回事,该如何解决?
不管在移动端还是PC端,我们都需要处理用户点击,这个最常用的事件。但在touch端click事件响应速度会比较慢,在较老的手机设备上会更为明显(300ms的延迟)。
这要追溯至 2007 年初。苹果公司在发布首款 iPhone 前夕,遇到一个问题:当时的网站都是为大屏幕设备所设计的。于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点的问题。
这当中最出名的,当属双击缩放(double tap to zoom),这也是会有上述 300 毫秒延迟的主要原因。双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。
那么这和 300 毫秒延迟有什么联系呢?
假定这么一个场景。用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。
鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。之前人们刚刚接触移动端的页面,在欣喜的时候往往不会care这个300ms的延时问题,可是如今touch端界面如雨后春笋,用户对体验的要求也更高,这300ms带来的卡顿慢慢变得让人难以接受。
那么我们该如何解决这个问题,可能有的同学会想到touchstart事件,这个事件响应速度很快啊,如果说开发的界面上面可点击的地方很少,要么用户滑动下手指就触发touchstart事件,也会让人崩溃的。大家可以参考如下的几种方法。
粗暴型:禁用缩放
关键是 user-scalable = no。
这个属于简单粗暴型的,虽然看似完美,但有一个致命的缺陷,当你必须完全禁用缩放来达到目的时候,就傻眼了,只有特定场景下的交互界面,此方案才可行,其它大多数情况,此法都不可行。
另外:Chrome 开发团队不久前宣布,在 Chrome 32 这一版中,他们将在。当然,没有双击缩放就没有 300 毫秒点击延迟。
指针事件 (Pointer Events)
指针事件最初由微软提出,现已进入 。这个草案规范旨在使用一个单独的事件模型,对所有输入类型,包括鼠标 (mouse)、触摸 (touch)、触控 (stylus) 等,进行统一的处理。
比如用css设置-ms-touch-action: none,那么对应的元素在被点击之后,浏览器不会启动缩放操作,也就避免了这个300ms延迟,但目前只有IE10+支持,目前touch开发的重点在safari和chrome,因此你懂的,此方案目前兼容性不好,不过chrome表示会在未来版本中支持的。
指针事件 (使非IE也支持)
上面也说道touch-action: none是一个办法,那么其它浏览器不支持怎么办呢?下面的几个类库是关于这方面的,感兴趣的可以去研究下:
touch-action: none这种方案虽然可以解决这个问题,但影响的面比较广,不是单纯的来解决300ms延时问题的,有可能会带来性能和其它操作上的隐患,慎用。
FastClick:闪亮登场
是FT Labs专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库。简而言之,FastClick 在检测到 touchend 事件的时候,会通过 DOM 自定义事件立即触发一个模拟 click 事件,并把浏览器在 300 毫秒之后真正触发的click事件阻止掉。
FastClick 的使用方法非常简单,在 window load 事件之后,在body上调用FastClick.attach()即可。
window.addEventListener( "load", function() {
FastClick.attach( document.body );
}, false );
attach方法虽可在更具体的元素上调用,直接绑定到body上可以确保整个应用都能受益。当 FastClick 检测到当前页面使用meta设置了user-scalable=no或者 touch-action 属性的解决方案时,会静默退出。可以说,这是真正的跨平台方案出来之前一种很好的变通方案。
就目前而言,FastClick 非常实际地解决 300 毫秒点击延迟的问题,唯一的缺点可能也就是该脚本的文件尺寸 (尽管它只有10kb)。如果你连这10kb都接受不了的话,那么移动端类库 jQuery和zepto.js都支持tap事件来解决这个问题,尽管它们的响应速度比FastClick慢一些。
正是因为有这些解决方案,那么首先还是挑选眼前更合适的吧,毕竟以后会不会出新标准来解决这个问题,谁都不知道,理论上来说FastClick也是属于替代方案,希望有一天touch 端的开发可以不走pc的路,让本来都苦逼的前端雪上加霜。
本文链接:
,转载务必注明来源链接。下次自动登录
现在的位置:
& 综合 & 正文
移动端WEB开发,click,touch,tap事件浅析
一、click 和 tap 比较
两者都会在点击时触发,但是在手机WEB端,click会有 200~300 ms,所以请用tap代替click作为点击事件。
singleTap和doubleTap 分别代表单次点击和双次点击。
二、关于tap的点透处理
在使用zepto框架的tap来移动设备浏览器内的点击事件,来规避click事件的延迟响应时,有可能出现点透的情况,即点击会触发非当前层的点击事件。
处理方式:
github上有一个叫做fastclick的库,它也能规避移动设备上click事件的延迟响应,
将它用script标签引入页面(该库支持AMD,于是你也可以按照AMD规范,用诸如require.js的模块加载器引入),并且在dom ready时初始化在body上,如:
$(function(){
newFastClick(document.body);
然后给需要“无延迟点击”的元素绑定click事件(注意不再是绑定zepto的tap事件)即可。
当然,你也可以不在body上初始化它,而在某个dom上初始化,这样,只有这个dom和它的子元素才能享受“无延迟”的点击
实践开发中发现,当元素绑定fastclick后,click响应速度比tap还要快一点点。哈哈
(2)、为元素绑定touchend事件,并在内部加上e.preventDefault();
$demo.on('touchend',function(e){
$demo.hide()
e.preventDefault();
三、touch事件touch是针对触屏手机上的触摸事件。现今大多数触屏手机webkit内核提供了touch事件的监听,让开发者可以获取用户触摸屏幕时的一些信息。
其中包括:touchstart,touchmove,touchend,touchcancel 这四个事件
touchstart,touchmove,touchend事件可以类比于mousedown,mouseover
,mouseup的触发。
touchstart : 当手指触摸到屏幕会触发;
touchmove : 当手指在屏幕上移动时,会触发;
touchend : 当手指离开屏幕时,会触发;
而touchcancel许多人不知道它在什么时候会被触发而忽略它,其实当你的手指还没有离开屏幕时,有系统级的操作发生时就会触发touchcancel,例如alert和confirm弹框,又或者是android系统的功能弹窗。
这4个事件的触发顺序为:
touchstart -& touchmove
-& …… -& touchmove -&touchend
但是单凭监听上面的单个事件,不足以满足我们去完成监听在触屏手机常见的一些手势操作,如双击、长按、左右滑动、缩放等手势操作。需要组合监听这些事件去封装对这类手势动作。
其实市面上很多框架都针对手机浏览器封装了这些手势,例如jqmobile、zepto、jqtouch,不过悲剧发生了,对于某些android系统(我自己测试到的在android 4.0.x),touchmove和touchend事件不能被很好的触发,举例子说明下:
比如手指在屏幕由上向下拖动页面时,理论上是会触发 一个 touchstart ,很多次 touchmove
,和最终的 touchend ,可是在android 4.0上,touchmove只被触发一次,触发时间和touchstart
差不多,而touchend直接没有被触发。这是一个非常严重的bug,在google Issue已有不少人提出
暂时我只发现在android 4.0会有这个bug,据说 ios 3.x的版本也会有。
而显然jqmobile、zepto等都没有意识到这个bug对监听实现带来的严重影响,所以在直接使用这些框架的event时,或多或少会出现兼容性问题!
&&&&推荐文章:
【上篇】【下篇】UC浏览器对于HTML5Touch事件的支持,其实是错的....
楼主是前端程序员一枚,
& & 近日有用户反映上我做的页面出现了无法使用的bug.
& & 经仔细debug后发现,楼主在用zepto开发移动端页面的时候用了swipe事件,这个事件没触发.
& & 查找后发现在zepto里,swipe是在 touchend 事件里触发的,如下图所示
QQ图片08.png (126.51 KB, 下载次数: 0)
日 18:01 上传
& & 但是在楼主一番测试之后,却发现原来UC对于touch事件的触发有问题.
& & 在Chrome上,手指触摸后进行拖动操作,然后手指离开屏幕,其触发顺序是 touchstart-&touchmove*n-&touchend,
& & 手指触摸后,马上离开屏幕,其触发顺序是touchstart-&touchend.
& & 在safari上得到的结果相同.
& & 而在UC上却是不同的结果
& & 在UC上,手指触摸后进行拖动操作,然后手指离开屏幕,其触发顺序是 touchstart-&touchmove*n,然后就没了!!!!
& &没了!!!
& &touchend事件呢?
& &楼主又进行了一次测试,发现touchend事件只在tap,也就是触摸到屏幕后马上离开时才会触发.
& & 楼主觉得这是个BUG啊!
& & UC的程序猿们,有没有好的解决方案?
& & PS:经楼主测试,zepto,jQuery Mobile的相关方法都有问题,希望解决.....
该帖共收到 13 条回复!
发表于 日 10:25
经与UC的开发讨论,得出如下结果~~
& & 1.UC在内核不响应touchend事件的时候会补发一个touchcancel事件,开发者需要同时监听end和cancel事件,专门为UC做一下优化
& & 2.在UC的move事件并不是连续触发多次,而是只触发一次。根据x,y的值可以来判断改变距离。
TKS,UC的开发很NICE呢~~
发表于 日 18:49
来自 HEDY_S801 Build
发表于 日 18:50
来自不明物体
发表于 日 19:23
发表于 日 21:26
来自 8190Q
提示: 作者被禁止或删除 内容自动屏蔽
发表于 日 13:43
大神骚等~已转给我们研发排查,有结果在此帖子回复哈
发表于 日 15:07
卧槽,看不懂!
发表于 日 15:25
大神骚等~已转给我们研发排查,有结果在此帖子回复哈
跪求解决。。。。
发表于 日 15:26
大神骚等~已转给我们研发排查,有结果在此帖子回复哈
跪求解决。。。。
发表于 日 20:33
来自ZTE -U
发表于 日 20:39
来自神X版UC
很深奥的样子
发表于 日 13:33
跪求解决。。。。
大神~请把QQ号发一下给我,这个问题我们研发解决了一个类似问题。这个可能是另外一个,请发一下QQ号给我们,研发大牛和你联系
发表于 日 15:15
本帖最后由 vajoy 于 日 15:18 编辑
为何要这么奇葩呢,本来已经觉得QQ内置浏览器很奇葩了。。。
touchmove得等到touchend的时候才触发,那简直就是把touchmove等同于touchend,还搞毛线touchcancle啊。。。
有的事情明明得move的时候就立刻触发的,搞的我现在都得在touchstart的事件里先var st = $win.scrollTop();
setTimeout(function(){
& && && && && && &&&if(st!=$win.scrollTop()){
& && && && && && && && &abc() //要触发的事件
& && && && && && &&&}
& && && && && & },200)
来判断用户是否滚动了屏幕。手机端html5触屏事件(touch事件)
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);
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。当前访客身份:游客 [
当前位置:
&input id="birth" ng-model="midate" type="date" ng-change="birthChange()" onChange="onChange()" /&
在安卓微信自带浏览器里,点击上面的输入框,调用系统的日期选择控件,选择一个然后点击确定,并不能触发ngChange事件,原生的onchange事件也不能触发。在pc平台是正常的。求解决办法?
demo在这里
共有1个答案
<span class="a_vote_num" id="a_vote_num_
可以触发呀。
Android5.1
WeChat6.3.5
--- 共有 5 条评论 ---
: 在angularjs的issue里找到相关的问题了,说是webkit的bug,也没有给出解决方案。我是开发功能,靠升级微信或者浏览器肯定不行了,只能绕过这种用法,另想办法了。
(2个月前)&nbsp&
: 不晓得是微信的问题还是安卓的问题。你升级下微信试试看。
(2个月前)&nbsp&
: 这个貌似是浏览器的bug,唉~
(2个月前)&nbsp&
: Android4.3 WeChat6.2.2 无法触发
(2个月前)&nbsp&
Android5.0.2
WeChat6.2.4
不能触发。
(2个月前)&nbsp&
更多开发者职位上
有什么技术问题吗?
双_双的其它问题
类似的话题

我要回帖

更多关于 js touchend 不触发 的文章

 

随机推荐