封装移动端事件库的意义
- 移动端使用click事件会有延迟
- 有许多左滑或者右滑的操作,原生js没有
- 有时业务会需要长按事件,原生js没有
开始封装
思路分析
- 既然是库,那么可以先写一个匿名自执行函数(保护内部变量不受污染,定义和调用合为一体)
- 内部结构分析
(a) 是需要外部调用,所以需要一个对外提供的接口
(b) 需要选取元素,进行操作,所以做一个初始方法
© 其它原型方法,比如点击,长按,滑动
开始操作
第一步:匿名自执行函数
(function (window){
//传入window,提高变量的查找效率
})(window);
第二步:内部架构搭建
对外提供的接口 + 初始化方法
(function (window){
function myMobile(selector){ //对外提供的接口。
//调用这个函数的原型对象上的_init方法,并返回
return myMobile.prototype._init(selector);
}
myMobile.prototype = {
/*初始化方法,获取当前查找的对象*/
_init: function (selector){
if (typeof selector == "string"){
//把查找到的元素存入到这个原型对象上。
this.ele = window.document.querySelector(selector);
//返回值其实就是原型对象。
return this;
}
},
}
})(window);
第三步:原型方法添加(全部的代码)
(function (window){
function myMobile(selector){
return myMobile.prototype._init(selector);
}
myMobile.prototype = {
/*初始化方法,获取当前query对象的方法*/
_init: function (selector){
if (typeof selector == "string"){
//把查找到的元素存入到这个原型对象上。
this.ele = window.document.querySelector(selector);
//返回值其实就是原型对象。
return this;
}
},
/*单击事件:
* 为了规避click的300ms的延迟,自定义一个单击事件
触摸时间小于500ms为单击事件
* */
tap: 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 < 500){
handler.call(this, e);
}
break;
}
}
},
/**
* 长按
* @param handler
* 大于500ms为长按事件
*/
longTag: function (handler){
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchmove", touchFn);
this.ele.addEventListener("touchend", touchFn);
var timerId;
function touchFn(e){
switch (e.type){
case "touchstart" : //500ms之后执行
timerId = setTimeout(function (){
handler.call(this, e);
}, 500)
break;
case "touchmove" :
//如果中间有移动也清除定时器
clearTimeout(timerId)
break;
case "touchend" :
//如果在500ms之内抬起了手指,则需要定时器
clearTimeout(timerId);
break;
}
}
},
/**
* 左侧滑动。
* 记录手指按下的左边,在离开的时候计算 deltaX是否满足左滑的条件
*/
slideLeft: function (handler){
this.ele.addEventListener("touchstart", touchFn);
this.ele.addEventListener("touchend", touchFn);
var startX, startY, endX, endY;
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;
//x方向移动大于y方向的移动,并且x方向的移动大于25个像素,表示在向左侧滑动
if (Math.abs(endX - startX) >= Math.abs(endY - startY) && startX - endX >= 25){
handler.call(this, e);
}
break;
}
}
},
/* 右侧滑动 */
rightLeft: function (e){
//TODO: 这里交给自己diy
}
}
//全局$赋值 可以直接调用
window.$ = window.myMobile = myMobile;
})(window);
页面调用
<!DOCTYPE>
<html lang="ZH-cn">
<head>
<meta charset="utf-8" >
<title>标题</title>
<meta name="keywords" content="关键字" />
<meta name="description" content="网页描述" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<script src="./event.js"></script>
</head>
<style>
</style>
<body>
<button>点我</button>
<script>
$("button").tap(function (e){
console.log("单击事件")
})
$("button").longTag(function (){
console.log("长按事件");
})
$("button").slideLeft(function (e){
console.log(this);
this.innerHTML = "左侧滑动了....."
})
</script>
</body>
</html>
FAQ
大家在使用的时候可能会有一些疑问,比如说我左滑事件为什么会触发单击事件?一般实际业务中,不存在这种场景。如果有,某一个元素既有单击事件又有左滑事件,那做一个节流阀就ok了,做一个判断,如果是左滑或者右滑事件就禁止触发单击事件。