国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

FastClick 原理解析

QiShare / 2177人閱讀

摘要:一直好奇是如何工作,于是花了幾天空余的時間一步步調試代碼,學習。一般會在時暫停游戲存檔等操作。這樣即使不監(jiān)聽事件也能實現(xiàn)點擊的偵聽。這種情況下一定會觸發(fā)事件。

Patience and perseverance will get paid.

這段時間開始實習了,在公司做hybrid,專職寫js,學習到了不少東西。一直好奇fastclick是如何工作,于是花了幾天空余的時間一步步調試代碼,學習fastclick。這篇文章可以結合者代碼看,希望可以給予需要學習fastclick的人一點思路。

有錯誤的地方希望指正,thk~

主流程

FastClick.attach()

FastClick(layer)

初始化化變量

this.trackingClick = false; //追蹤一個click
this.trackingClickStart = 0; //追蹤時間
this.targetElement = null; // 目標元素
this.touchStartX = 0;// X坐標
this.touchStartY = 0;// y坐標
this.lastTouchIndentifier = 0;
this.touchBoundary = 10;//邊界條件(是否是一個點擊)
this.layer = layer;//layer可以是document.body/document.documentElement

安卓設備綁定鼠標事件(在捕獲階段,為的是第一時間處理到事件)

layer.addEventListener("mouseover",bind(this.onMouse,this),true);
layer.addEventListener("mousedown",bind(this.onMouse,this),true);
layer.addEventListener("mouseup",bind(this.onMouse,this),true);

綁定touch和click事件(判定是否是click行為,取消之前的click),

//最先捕獲到
layer.addEventListener("click", bind(this.onClick, this), true);
//冒泡階段捕獲
layer.addEventListener("touchstart", bind(this.onTouchStart, this), false);
layer.addEventListener("touchmove", bind(this.onTouchMove, this), false);
layer.addEventListener("touchend", bind(this.onTouchEnd, this), false);
layer.addEventListener("touchcancel", bind(this.onTouchCancel, this), false);

判斷是否存在stopImmediatePropagation,如果不存在則進行hack,在onMouse中會利用stopImmediatePropagation來阻止其他點擊事件的回調函數(shù)的執(zhí)行,避免ghost click的現(xiàn)象

onMouse中,防止點透等詭異現(xiàn)象的代碼

if (!this.needsClick(this.targetElement) || this.cancelNextClick) {
    // Prevent any user-added listeners declared on FastClick element from being fired.
    if (event.stopImmediatePropagation) {
        event.stopImmediatePropagation();
    } else {
        // Part of the hack for browsers that don"t support Event#stopImmediatePropagation (e.g. Android 2)
        event.propagationStopped = true;
    }
    // Cancel the event
    event.stopPropagation();
    event.preventDefault();
    return false;
}

判斷是否通過onclick綁定了回調函數(shù),如果有讀取出來,使用addEventListener,綁定事件處理函數(shù)

if (typeof layer.onclick === "function") {
    // Android browser on at least 3.2 requires a new reference to the function in layer.onclick
    // - the old one won"t work if passed to addEventListener directly.
    oldOnClick = layer.onclick;
    layer.addEventListener("click", function (event) {
        oldOnClick(event);
    }, false);
    layer.onclick = null;
}

觸發(fā)click流程 onTouchStart()

當一些更高級別的事件發(fā)生的時候(如電話接入或者彈出信息)會取消當前的touch操作,即觸發(fā)ontouchcancel。一般會在ontouchcancel時暫停游戲、存檔等操作。因此在調試的時候才會在touchStart之后,就觸發(fā)了touchCancel

直接斷點touchend,在控制臺打印,可以看到touchstart也是觸發(fā)的了、

判斷是不是單點觸發(fā)

if (event.targetTouches.length > 1) {
    return true;
}

獲取目標對象和touch事件對象

targetElement = this.getTargetElementFromEventTarget(event.target);
touch = event.targetTouches[0];

根據(jù)touch事件對象,設置一些初始屬性

this.trackingClick = true; //標識跟蹤該次點擊
this.trackingClickStart = event.timeStamp;//點擊開始的時間
this.targetElement = targetElement;//目標元素

this.touchStartX = touch.pageX; //x坐標
this.touchStartY = touch.pageY; //y坐標

onTouchMove()

如果剛觸發(fā)完touchstart事件馬上就觸發(fā)touchend,說明手指只是輕輕點了一下屏幕,也就是所謂的點擊操作。這樣即使不監(jiān)聽click事件也能實現(xiàn)點擊的偵聽。不過這里有一個實際的情況,很多山寨的Android設備屏幕很不靈敏,需要使勁按下才能有所感知。這種情況下一定會觸發(fā)touchmove事件。所以針對Android設備的點擊操作可以適當放寬,比如touchstart和touchend之間可以允許有少量幾個touchmove,并且touchmove的距離不能超過多少個像素等等

因此也是需要監(jiān)聽onTouchMove,并且加入判斷

// If the touch has moved, cancel the click tracking
if ( 
    this.targetElement !== this.getTargetElementFromEventTarget(event.target) 
    || this.touchHasMoved(event)
    ) {
    this.trackingClick = false;
    this.targetElement = null;
}
onTcouhEnd()

在touchend的時候,執(zhí)行this.onTouchEnd(上個流程綁定了)

判斷是否在追蹤該click,在this.onTouchMove的時候,如果移動的距離大于邊界,則將this.trackingClick=false,在touchend就不用再判斷是否為一個click的行為

if(!this.trackingClick){
    return true;
}

獲取目標元素標簽,需要根據(jù)標簽名來做一些判斷

targetTagName = targetElement.tagName.toLowerCase();

如果是label,進行bug修復

執(zhí)行this.needsFocus,針對表單元素的focus和click事件的處理

先focus表單

在觸發(fā)點擊事件

針對IOS,滾動層bug修復

判斷元素是否需要原生的click,實際上就是有些行為還是要瀏覽器來執(zhí)行默認的行為

表單元素disabled,點擊不了

type=file的控件

video

label

如果不需要,則發(fā)送一個click事件

event.preventDefault();
this.sendClick(targetElement, event);

sendClick()流程

在一些安卓設備上,必須讓一個元素blured,才能使創(chuàng)建的clickEvent生效

if (document.activeElement && document.activeElement !== targetElement) {
    document.activeElement.blur();
}

創(chuàng)建clickEvent,使用touch事件對象的屬性來進行初始化

clickEvent = document.createEvent("MouseEvents");
clickEvent.initMouseEvent(
        this.determineEventType(targetElement), //bug修復針對select
        true, 
        true, 
        window, 
        1, 
        touch.screenX, 
        touch.screenY, 
        touch.clientX, 
        touch.clientY, 
        false, false, false, false, 0, null);

創(chuàng)建完成之后,賦予對象一個額外的屬性,在onClick中可以使用,然后觸發(fā)點擊事件,此時通過addEventListner綁定的click事件就會觸發(fā)

clickEvent.forwardedTouchEvent = true;
targetElement.dispatchEvent(clickEvent);

onClick()

addEventListener添加會按照添加順序執(zhí)行

onClick作為第一個注冊監(jiān)聽的,因此,是第一個執(zhí)行的click事件的回調函數(shù)

特殊情況處理,一般不會執(zhí)行

/*
    It"s possible for another FastClick-like library delivered with third-
    party code to fire a click event before FastClick does (issue #44). In 
    that case, set the click-tracking flag back to false and return early. 
    This will cause onTouchEnd to return early.
*/
if (this.trackingClick) {
    this.targetElement = null;
    this.trackingClick = false;
    return true;
}

特殊情況處理

if (event.target.type === "submit" && event.detail === 0) {
    return true;
}

執(zhí)行onMouse

//創(chuàng)建時,附帶的一個屬性
if (event.forwardedTouchEvent) {
    return true;
}

最后返回為真

return permitted; //true

注意:在這里的return的true或false并不會影響綁定的其他回調函數(shù)的執(zhí)行

總結

完整的看完代碼,深深感覺到移動端的坑非常的多,很有怪異的現(xiàn)象因為沒有遇到過暫時理解不了,希望之后可以繼續(xù)研究,把代碼完全讀懂。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79839.html

相關文章

  • 2019 再聊移動端 300ms 延遲及 fastClick 原理解析

    摘要:前言最近公司新開了一條業(yè)務線,有幸和大佬們一起從頭開始構建一套適合新業(yè)務的框架。俗話說得好呀,適合自己的才是最好的 前言 最近公司新開了一條業(yè)務線,有幸和大佬們一起從頭開始構建一套適合新業(yè)務的框架。俗話說得好呀,適合自己的才是最好的

    skinner 評論0 收藏0
  • 2019 再聊移動端 300ms 延遲 -- 附 fastClick 原理解析

    摘要:前言最近公司新開了一條業(yè)務線,有幸和大佬們一起從頭開始構建一套適合新業(yè)務的框架。俗話說得好呀,適合自己的才是最好的前言 (Foreword) 最近公司新開了一條業(yè)務線,有幸和大佬們一起從頭開始構建一套適合新業(yè)務的框架。俗話說得好呀,適合自己的才是最好的

    k00baa 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<