>  기사  >  웹 프론트엔드  >  모바일 단말기의 300ms 지연 문제를 해결하기 위해 기본 JS를 사용하여 Tap 이벤트를 캡슐화합니다.

모바일 단말기의 300ms 지연 문제를 해결하기 위해 기본 JS를 사용하여 Tap 이벤트를 캡슐화합니다.

高洛峰
高洛峰원래의
2016-11-19 11:28:561843검색

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(&#39;#test&#39;).addTapEvent(function(){
    alert(&#39;this is a tap event&#39;);
})

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(&#39;touchstart&#39;, function() {
                    tapStartTime = event.timeStamp;                    var touch = event.changedTouches[0];
                    tapStartClientX = touch.clientX;
                    tapStartClientY = touch.clientY;
                    cancleClick = false;
                })                this.addEventListener(&#39;touchmove&#39;, 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(&#39;touchend&#39;, function() {
                    tapEndTime = event.timeStamp;                    if (!cancleClick && (tapEndTime - tapStartTime) <= tapTime) {
                        callback();
                    }
                })
            }
        }        var ul = document.querySelector(&#39;ul&#39;);        for (var i = 1; i <= 20; i++) {            var li = document.createElement(&#39;li&#39;);
            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(&#39;li&#39;);
            li.innerHTML = j;
            li.onclick = function() {                var x = j;                return function() {
                    alert(x);
                }
            }()
            ul.appendChild(li);
        }    </script></html>


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.