移动设备上的浏览器默认会在用户点击屏幕大约延迟300毫秒后才会触发点击事件,这是为了检查用户是否在做双击。为了能够立即响应用户的点击事件,我们需要对移动端的点击事件做下处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.box1 {
width: 200px;
height: 100px;
background: red;;
}
</style>
</head>
<body>
<div class="box1" id='box11'></div>
</body>
<script src="h5.js"></script>
<script>
window.onload = function() {
var eleBox = document.getElementById('box11');
eleBox.addEventListener('click', function() {
console.log('click')
})
eleBox.addEventListener('touchstart', function() {
console.log('touchstart')
})
}
</script>
</html>
打开浏览器,调成手机模式,点击div,会发现touchstart先触发,click会在300ms后触发,这就是手机端点击时间的延迟。
我们给div增加一个startend事件,看看会怎样?
eleBox.addEventListener('touchend', function() {
console.log('touchend')
})
点击发现,touchstart和touchend都在click之前触发,这就是说,如果我们禁止掉click事件,用touchstart和touchend两个事件的时间差去处理click事件,是不是就能解决300ms的延迟问题了呢?我们来试一下。
fastClick.js
(function(window) {
'use stirct'
function myMobile(selector) {
return myMobile.prototype._init(selector)
}
myMobile.prototype = {
_init: function(selector) {
if (typeof selector === 'string') {
this.ele = window.document.querySelector(selector);
return this;
}
},
// 单机事件
tab: function(handler) {
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchend", touchFn);
var startTime,
endTime;
function touchFn(e) {
e.preventDefault();
switch (e.type) {
case 'touchstart':
startTime = new Date().getTime();
break;
case 'touchend':
endTime = new Date().getTime();
if(endTime - startTime < 200) {
handler.call(this,e)
}
break;
}
}
},
window.myMobile = myMobile;
})(window)
上面代码意思是,两次时间间隔如果小于200ms,就触发传递进来的事件,可以代替点击事件来用。
html中引入fastClick.js文件
var ele = myMobile('#box11');
ele.tab(function(e) {
console.log('点击事件')
})
点击事件被触发了,并且是⌚️小于300ms。这样就解决了300延迟问题。是不是很简单。
同理我们也可以增加长按事件,左右滑动,上下滑动事件。
(function(window) {
'use stirct'
function myMobile(selector) {
return myMobile.prototype._init(selector)
}
myMobile.prototype = {
_init: function(selector) {
if (typeof selector === 'string') {
this.ele = window.document.querySelector(selector);
return this;
}
},
// 单机事件
tab: function(handler) {
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchend", touchFn);
var startTime,
endTime;
function touchFn(e) {
e.preventDefault();
switch (e.type) {
case 'touchstart':
startTime = new Date().getTime();
break;
case 'touchend':
endTime = new Date().getTime();
if(endTime - startTime < 200) {
handler.call(this,e)
}
break;
}
}
},
// 长按事件
longTap: function(handler) {
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchmove", touchFn);
this.ele.addEventListener("touchend", touchFn);
var timeId;
function touchFn(e) {
e.preventDefault();
switch (e.type) {
case 'touchstart':
timeId = setTimeout(function() {
handler.call(this,e)
}, 500)
break;
case 'touchmove':
clearTimeout(timeId);
break;
case 'touchend':
clearTimeout(timeId);
break;
}
}
},
// 左侧滑动
slide: function(fun) {
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchend", touchFn);
var startX, startY, endX, endY, moveLengthX, moveLengthY;
function touchFn(e) {
e.preventDefault();
var firstTouch = e.changedTouches[0];
switch (e.type) {
case 'touchstart':
startX = firstTouch.pageX;
startY = firstTouch.pageY;
break;
case 'touchend':
endX = firstTouch.pageX;
endY = firstTouch.pageY;
moveLengthX = Math.abs(endX - startX);
moveLengthY = Math.abs(endY - startY);
fun.call(this, moveLengthX,moveLengthY,e)
break;
}
}
},
slideLeftRight: function(handler) {
this.slide(function(moveLengthX, moveLengthY, e) {
// moveLengthX >= moveLengthY 确保是x轴的移动
if( moveLengthX >= moveLengthY && moveLengthX >= 25 ) {
handler(this, e);
}
});
},
slideTopBottom: function(handler) {
this.slide(function(moveLengthX, moveLengthY, e) {
if( moveLengthY >= moveLengthX && moveLengthY >= 25) {
handler(this, e);
}
});
}
}
window.myMobile = myMobile;
})(window)
这里只是告诉你原理,实际操作的过程中,会发现左右滑动或者上下滑动太快的话会触发点击事件,所以不能同时使用,如果想知道怎么解决,可以去看fastClick.js的源码,里面有很多兼容性问题,也有很多事件追踪,可以解决上述问题。
ele.longTap(function(e) {
console.log('长按事件')
})
ele.slideLeftRight(function(e) {
console.log('左右滑动事件')
})
ele.slideTopBottom(function(e) {
console.log('上下滑动事件')
})
有兴趣的可以去测试一下。代码都贴在这里了。
谷歌浏览器56个版本以后,阻止默认行为会报错
需要加一个样式解决这个问题
* {
touch-action: none;
}