FastClick
현재 이 문제를 해결할 수 있는 기성 플러그인 fastclick이 있지만 단점도 있습니다.
최신 버전의 플러그인 크기 GitHub의 용량은 25.4kb이며, 경량화가 대세이며, 에너지 절약이 대세입니다.
기본 아이디어는 기본 클릭 시간을 취소하고 현재 dom 노드의 유형을 결정하고 해당 작업을 수행하는 것입니다. 이 판단 과정은 상대적으로 번거롭습니다.
MyTapEvent
현재 WeChat 프로젝트를 진행 중입니다. fastclick 플러그인의 몇 가지 단점으로 인해 주요 아이디어는 다음과 같습니다.
생각하기
탭 이벤트에는 touchstart, touchmove(약간의 움직임), touchend의 세 가지 상태가 포함됩니다.
콜백 메서드는 touchend 후에 실행됩니다.
다음에 따라 클릭을 취소합니다. 크롬 브라우저의 기본 판단 이동량과 손가락 오프셋(가로 또는 세로)이 15px를 초과하면 스크롤로 판단하여 탭 이벤트가 취소됩니다.
너무 길면 클릭으로 간주되지 않습니다. 기본 시간 간격은 500ms입니다
HTMLElement를 사용하여 프로토타입을 확장하여 쉽게 이벤트를 추가하세요
한 번만 로드되도록 싱글톤 모드를 사용하세요
자, 일단 자리를 잡으면 코드 작성이 훨씬 더 명확해질 것입니다:
if (!HTMLElement.prototype.addTapEvent) { HTMLElement.prototype.addTapEvent = function(callback) { var tapStartTime = 0, tapEndTime = 0, tapTime = 500, //tap等待时间,在此事件下松开可触发方法 tapStartClientX = 0, tapStartClientY = 0, tapEndClientX = 0, tapEndClientY = 0, tapScollHeight = 15, //水平或垂直方向移动超过15px测判定为取消(根据chrome浏览器默认的判断取消点击的移动量) cancleClick = false; this.addEventListener('touchstart', function() { tapStartTime = event.timeStamp; var touch = event.changedTouches[0]; tapStartClientX = touch.clientX; tapStartClientY = touch.clientY; cancleClick = false; }) this.addEventListener('touchmove', function() { var touch = event.changedTouches[0]; tapEndClientX = touch.clientX; tapEndClientY = touch.clientY; if ((Math.abs(tapEndClientX - tapStartClientX) > tapScollHeight) || (Math.abs(tapEndClientY - tapStartClientY) > tapScollHeight)) { cancleClick = true; } }) this.addEventListener('touchend', function() { tapEndTime = event.timeStamp; if (!cancleClick && (tapEndTime - tapStartTime) <= tapTime) { callback(); } }) } }
Usage
HTMLElement.addTapEvent(function(){ //do something...}) 如:document.querySelect('#test').addTapEvent(function(){ alert('this is a tap event'); })
Case
여기 있습니다 클로저에 대한 지식도 포함된 모바일 케이스에서 처음 20개 항목은 탭 이벤트이고 마지막 30개 항목은 클릭 이벤트입니다. 두 가지 방법의 차이를 휴대폰에서 직접 체험해 보세요.
<style media="screen"> li { padding: 20px; }</style><!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-touch-fullscreen" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no,email=no"> <meta name="x5-orientation" content="portrait"> <title>test</title> </head> <body> <ul></ul> </body> <script type="text/javascript"> if (!HTMLElement.prototype.addTapEvent) { HTMLElement.prototype.addTapEvent = function(callback) { var tapStartTime = 0, tapEndTime = 0, tapTime = 500, //tap等待时间,在此事件下松开可触发方法 tapStartClientX = 0, tapStartClientY = 0, tapEndClientX = 0, tapEndClientY = 0, tapScollHeight = 15, //水平或垂直方向移动超过15px测判定为取消(根据chrome浏览器默认的判断取消点击的移动量) cancleClick = false; this.addEventListener('touchstart', function() { tapStartTime = event.timeStamp; var touch = event.changedTouches[0]; tapStartClientX = touch.clientX; tapStartClientY = touch.clientY; cancleClick = false; }) this.addEventListener('touchmove', function() { var touch = event.changedTouches[0]; tapEndClientX = touch.clientX; tapEndClientY = touch.clientY; if ((Math.abs(tapEndClientX - tapStartClientX) > tapScollHeight) || (Math.abs(tapEndClientY - tapStartClientY) > tapScollHeight)) { cancleClick = true; } }) this.addEventListener('touchend', function() { tapEndTime = event.timeStamp; if (!cancleClick && (tapEndTime - tapStartTime) <= tapTime) { callback(); } }) } } var ul = document.querySelector('ul'); for (var i = 1; i <= 20; i++) { var li = document.createElement('li'); li.innerHTML = i; li.addTapEvent(function() { var x = i; return function() { alert(x); } }()) ul.appendChild(li); } for (var j = 21; j <= 50; j++) { var li = document.createElement('li'); li.innerHTML = j; li.onclick = function() { var x = j; return function() { alert(x); } }() ul.appendChild(li); } </script></html>