移动端touch事件影响click事件以及在touchmove添加preventDefault导致页面无法滚动的解决方法
这两天自己在写一个手机网页,用到了触屏滑动的特效,就是往右滑动的时候左侧隐藏的菜单从左边划出来。
做完之后在手机原生浏览器中运行正常,但在QQ和微信中打开,发现touchmove只会触发一次,而且touchend也经常不触发。
之后百度了一下这个问题,原因是
主要是由于200ms超时导致内核不一定会一直处理touchmove事件,一旦超时会将后续所有的事件转交给UI处理,导致touchmove不会一直触发。
为了解决开发者需要,建议开发者在touchstart时调用event.preventDefault,这样就可以保证内核会一起触发touchmove事件了。
地址:http://bbs.mb.qq.com/thread-201794-1-1.html
根据上面所说,在touchstart中添加了event.preventDefault()方法,在QQ和微信中果然正常了。
但是!!!页面中的超链接点击没反应了!!!给其他地方加的click事件也不触发了!!!
之后继续百度,得知当在移动端上点击屏幕时,会依次触发touchstart,touchmove,touchend,click事件。
之后测试了一下,发现正确的触发过程应该是:touchstart→touchmove→touchend或者touchstart→touchend→click。
如果在点击屏幕的时候手指滑动的话,是不会触发click事件的。
参考地址:http://www.tuicool.com/articles/3QZ7jeV
上面说event.preventDefault()的方法,会阻止事件的默认行为。可以通过调用preventDefault()方法,可以阻止后面事件的触发。
我知道event.preventDefault()会阻止a标签默认的动作(跳转到href指定的页面),但是为什么click也不触发了呢?
之后我大胆推测了一下:
会不会是因为在移动端click事件的触发条件就是必须touchstart和touchend同时触发才能触发click呢?
我在touchstart中调用了event.preventDefault方法,是不是让浏览器误以为没有触发touchstart事件,只触发了touchend事件,所以没有触发click事件呢?
之后我删除了touchstart中的event.preventDefault方法,果然超链接和click事件都触发了,但是前面说的问题又出现了,在QQ和微信中touchmove和touchend又出问题了。
怎么办呢?
后来突然脑袋灵光一闪,既然在touchstart中加了event.preventDefault会导致不触发click事件,那我在touchmove中加可以吧?
抱着试一试的心态,果然好了,click能顺利触发,QQ和微信中也没有问题,我以为这样就好了,但是为什么页面不能滚动了?
原来touchmove中添加event.preventDefault方法之后会阻止浏览器默认的滚动。。。
所以页面无法滚动了,之后又去找找找,找了很久一直没找到怎么解决这个问题,突然想起之后用的一个移动端的图片轮播插件,
为什么他们可以左右滑动,不影响click事件和a标签,也不影响页面的滚动。
然后我打开了这个插件的源码,终于在touchmove中找到了答案
在touchmove中有这样一段代码(下面是我自己抄过来简化过的):
var w = x<0?x*-1:x; //x轴的滑动值
var h = y<0?y*-1:y; //y轴的滑动值
if(w>h){ //如果是在x轴中滑动
event.preventDefault();
}
就是在touchmove中判断x轴和y轴的移动值,判断当前是往哪个方向滑动,如果是在x轴上滑动(左右),就调用event.preventDefault()方法,如果是在y轴上滑动(上下),就不调用event.preventDefault()。
然后测试一下,QQ和微信中特效没有问题,click事件和a标签链接也可以顺利触发,页面滚动也没有问题。
所有问题终于解决了。。
总结一下:
在QQ和微信(当然还包括其他浏览器,不过我没测试过)中如果有需要用到touch事件做的特效一定要在touchstart或者touchmove中添加event.preventDefault()方法。
在touchstart中如果有event.preventDefault()方法, 将不会触发click事件和a标签方法。在这里可以使用tap代替click,但是a标签的话就不太方便了。
如果在touchmove中有event.preventDefault()方法,最好加上方向判断,当然如果你页面内容不需要滚动条就不需要加判断了。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JVM自定义类加载器
- Java代理相关:JDK动态代理、CGLIB动态代理
- Tomcat CPU占用100%异常分析与处理
- Solr基本搭建及MySQL配置
- Tomcat, Jre 证书相关
- zookeeper集群搭建
- Maven Jar包制作与上传及基本使用
- 当你在`bind 0.0.0.0`的时候,你实际在做什么
- Hadoop Hive Hbase Kylin 环境搭建
- Spring MVC 学习
- RSeQC判断链特异性(strand-specific)
- bigWigMerge合并bigwig文件
- WPF桌面开发集成Nginx服务器
- chrome浏览器拦截(block)特定网站某些请求的方法
- 聊一聊:一道 Promise 链式调用的题目