封装移动端事件库的意义
移动端使用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了,做一个判断,如果是左滑或者右滑事件就禁止触发单击事件。