自定義封裝移動端事件庫

封裝移動端事件庫的意義

  1. 移動端使用click事件會有延遲
  2. 有許多左滑或者右滑的操作,原生js沒有
  3. 有時業務會需要長按事件,原生js沒有

開始封裝

思路分析

  1. 既然是庫,那麼可以先寫一個匿名自執行函數(保護內部變量不受污染,定義和調用合爲一體)
  2. 內部結構分析
    (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了,做一個判斷,如果是左滑或者右滑事件就禁止觸發單擊事件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章