JS中touchstart事件与click事件冲突的解决方法


Posted in Javascript onMarch 12, 2018

前言

移动互联网是未来的发展趋势,现在国内很多互联网大佬都在争取移动这一块大饼,如微信及支付宝是目前比较成功的例子,当然还有各种APP和web运用。

下面这篇文章主要介绍了关于JS中touchstart事件与click事件冲突解决的相关内容,下面话不多说了,来一起看看详细的介绍吧。

一 · 业务场景的描述

在对已完成的PC站点进行移动端适配时,我们想要站点在移动设备上有更快的响应速度,以带给用户更好的体验,此时,我们应该使用移动设备专用的事件系统,例如,使用 touchstart 事件代替 click 事件。

为什么这样效果会更好呢?根据Google开发者文档中的描述:

移动设备上的浏览器将会在 click 事件触发时延迟 300ms ,以确保这是一个“单击”事件而非“双击”事件。
而对于 touchstart 事件而言,则会在用户手指触碰屏幕的一瞬间触发所绑定的事件。所以,使用 touchstart 替换 click 事件的意义在于,帮助用户在每次点击时节省 300ms 的时间。在页面频繁需要点击,或者点击发生在动画中,对动画流畅度有较高要求的情境下,使用这种技术是非常必要的。

但是,让我们回到我们的初始场景,在 PC端站点适配移动端时 我们不能简单的进行 touchstart和 click 事件的替换,因为PC并不能识别 touchstart 事件。

二 · 产生冲突的原因

当然,我们可以给某个元素同时绑定 touchstart 和 click 事件,但这将会导致本篇文章解决的问题 -- 这两个事件在移动设备上会发生冲突。

由于移动设备能够同时识别 touchstart 和 click 事件,因此当用户点击目标元素时,绑定在目标元素上的 touchstart 事件与 click 事件(约300ms后)会依次被触发,也就是说,我们所绑定的回调函数会被执行两次!。这显然不是我们想要的结果。

三 · 解决方案

针对这样的情境,有以下两种解决方案:

(一)使用 preventDefault

第一种解决方案是使用事件对象中的 preventDefault 方法,preventDefault 方法的作用在于:阻止元素默认事件行为的发生,但有意思的是,当我们在目标元素同时绑定 touchstart 和 click 事件时,在 touchstart 事件回调函数中使用该方法,可以阻止后续 click 事件的发生。

这从道理上是讲不通的,毕竟,我们添加的 click 事件并不是元素的“默认事件”,但它确实奏效了,或者说,被浏览器实现了,因此我们可以使用该方法解决移动设备上 touchstart 事件与 click 事件的冲突问题,具体代码如下:

const Button = document.getElementById("targetButton")
Button.addEventListener("touchstart", e => {
 e.preventDefault()
 console.log("touchstart event!")
})
 
Button.addEventListener("click", e => {
 e.preventDefault()
 console.log("click event!")
})

当你在浏览器上模拟移动设备后点击目标元素,只会在控制台看到 touchstart event! 字段,很显然,click 事件被成功阻止了。

总结

使用该方法的优点在于简单粗暴,直接有效,能够很好的实现我们的目标,但缺点在于, preventDefault 方法为阻止 click 事件的方式是浏览器实现上的,而不是 preventDefault 原理上的,这会带来一些不确定性,虽然我暂时尚未发现该方法失效的具体场景。

(二)基于功能检测绑定事件

我们可以通过判断浏览器是否支持 touchstart 事件来封装元素的点击事件,这样客户端会根据当前环境判定元素应该绑定的事件类型,代码如下:

const Button = document.getElementById("targetButton")
const clickEvent = (function() {
 if ('ontouchstart' in document.documentElement === true)
 return 'touchstart';
 else
 return 'click';
})();
 
Button.addEventListener(clickEvent, e => {
 console.log("things happened!")
})

总结

该方法的优点在于,我们通过增加一次判断,为元素减少了一个不必要的事件绑定,从而避免了 touchstart 与 click 事件的冲突问题。这种方法避免了我们书写两次同样的代码,并且相较于第一种方法更加符合逻辑,因此是我所推荐的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript使用prototype定义对象类型(转)[
Dec 22 Javascript
js浮动图片的动态效果
Jul 10 Javascript
JQuery与Ajax调用新浪API获取短网址的代码
Feb 07 Javascript
JS实现单行文字不间断向上滚动的方法
Jan 29 Javascript
Node.js node-schedule定时任务隔多少分钟执行一次的方法
Feb 10 Javascript
JS判断字符串包含的方法
May 05 Javascript
浅析js中substring和substr的方法
Nov 09 Javascript
微信小程序  自定义创建详细介绍
Oct 27 Javascript
微信小程序注册60s倒计时功能 使用JS实现注册60s倒计时功能
Aug 16 Javascript
JavaScript设计模式之缓存代理模式原理与简单用法示例
Aug 07 Javascript
Vue.js数字输入框组件使用方法详解
Oct 19 Javascript
前端深入理解Typescript泛型概念
Mar 09 Javascript
Node.JS循环删除非空文件夹及子目录下的所有文件
Mar 12 #Javascript
Javascript中prototype与__proto__的关系详解
Mar 11 #Javascript
js中document.write和document.writeln的区别
Mar 11 #Javascript
Javascript 编码约定(编码规范)
Mar 11 #Javascript
JavaScript获取移动设备型号的实现代码(JS获取手机型号和系统)
Mar 10 #Javascript
js经验分享 JavaScript反调试技巧
Mar 10 #Javascript
webpack打包node.js后端项目的方法
Mar 10 #Javascript
You might like
PHP中array_map与array_column之间的关系分析
2014/08/19 PHP
PHP 微信支付类 demo
2015/11/30 PHP
php微信高级接口调用方法(自定义菜单接口、客服接口、二维码)
2016/11/28 PHP
[原创]PHPCMS遭遇会员投稿审核无效的解决方法
2017/01/11 PHP
仅用[]()+!等符号就足以实现几乎任意Javascript代码
2010/03/01 Javascript
js中一维数组和二位数组中的几个问题示例说明
2014/07/17 Javascript
Angularjs编写KindEditor,UEidtor,jQuery指令
2015/01/28 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
2015/03/14 Javascript
js实现无缝滚动特效
2015/12/20 Javascript
vue省市区三联动下拉选择组件的实现
2017/04/28 Javascript
基于jQuery对象和DOM对象和字符串之间的转化实例
2017/08/08 jQuery
JavaScript 隐性类型转换步骤浅析
2018/03/15 Javascript
微信小程序实现长按删除图片的示例
2018/05/18 Javascript
解决vue路由后界面没有变化,但是链接有的问题
2018/09/01 Javascript
浅谈Vue render函数在ElementUi中的应用
2018/09/06 Javascript
微信小程序如何连接Java后台
2019/08/08 Javascript
微信小程序纯文本实现@功能
2020/04/08 Javascript
[43:32]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第一场
2014/05/26 DOTA
python的dict,set,list,tuple应用详解
2014/07/24 Python
浅谈Python的垃圾回收机制
2016/12/17 Python
python数据清洗系列之字符串处理详解
2017/02/12 Python
python交互模式下输入换行/输入多行命令的方法
2019/07/02 Python
Python远程开发环境部署与调试过程图解
2019/12/09 Python
Python WebSocket长连接心跳与短连接的示例
2020/11/24 Python
很酷的HTML5电子书翻页动画特效
2016/02/25 HTML / CSS
移动端HTML5开发神器之vconsole详解
2020/12/15 HTML / CSS
美国女孩洋娃娃店:American Girl
2017/10/24 全球购物
在使用非全零作为空指针内部表达的机器上, NULL是如何定义
2014/11/09 面试题
介绍一下JMS编程步骤
2015/09/22 面试题
前台接待员岗位职责
2014/01/02 职场文书
大学考试作弊检讨书
2014/01/30 职场文书
中专自我鉴定
2014/02/05 职场文书
慈善晚会策划方案
2014/05/14 职场文书
房屋维修申请报告
2015/05/18 职场文书
居住证明范文
2015/06/17 职场文书
JavaScript异步操作中串行和并行
2021/11/20 Javascript