封裝移動端事件庫的意義
- 移動端使用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了,做一個判斷,如果是左滑或者右滑事件就禁止觸發單擊事件。