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

資訊專欄INFORMATION COLUMN

淺談js防抖和節(jié)流

opengps / 2776人閱讀

摘要:防抖和節(jié)流嚴格算起來應(yīng)該屬于性能優(yōu)化的知識,但實際上遇到的頻率相當高,處理不當或者放任不管就容易引起瀏覽器卡死。

防抖和節(jié)流嚴格算起來應(yīng)該屬于性能優(yōu)化的知識,但實際上遇到的頻率相當高,處理不當或者放任不管就容易引起瀏覽器卡死。所以還是很有必要早點掌握的。(信我,你看完肯定就懂了)

從滾動條監(jiān)聽的例子說起

先說一個常見的功能,很多網(wǎng)站會提供這么一個按鈕:用于返回頂部。

這個按鈕只會在滾動到距離頂部一定位置之后才出現(xiàn),那么我們現(xiàn)在抽象出這個功能需求-- 監(jiān)聽瀏覽器滾動事件,返回當前滾條與頂部的距離
這個需求很簡單,直接寫:

function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log("滾動條位置:" + scrollTop);
}
window.onscroll  = showTop

但是!

在運行的時候會發(fā)現(xiàn)存在一個問題:這個函數(shù)的默認執(zhí)行頻率,太!高!了!。 高到什么程度呢?以chrome為例,我們可以點擊選中一個頁面的滾動條,然后點擊一次鍵盤的【向下方向鍵】,會發(fā)現(xiàn)函數(shù)執(zhí)行了8-9次

然而實際上我們并不需要如此高頻的反饋,畢竟瀏覽器的性能是有限的,不應(yīng)該浪費在這里,所以接著討論如何優(yōu)化這種場景。

防抖(debounce)

基于上述場景,首先提出第一種思路:在第一次觸發(fā)事件時,不立即執(zhí)行函數(shù),而是給出一個期限值比如200ms,然后:

如果在200ms內(nèi)沒有再次觸發(fā)滾動事件,那么就執(zhí)行函數(shù)

如果在200ms內(nèi)再次觸發(fā)滾動事件,那么當前的計時取消,重新開始計時

效果:如果短時間內(nèi)大量觸發(fā)同一事件,只會執(zhí)行一次函數(shù)。

實現(xiàn):既然前面都提到了計時,那實現(xiàn)的關(guān)鍵就在于setTimeOut這個函數(shù),由于還需要一個變量來保存計時,考慮維護全局純凈,可以借助閉包來實現(xiàn):

/*
* fn [function] 需要防抖的函數(shù)
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null //借助閉包
    return function() {
        if(timer){
            clearTimeout(timer) //進入該分支語句,說明當前正在一個計時過程中,并且又觸發(fā)了相同事件。所以要取消當前的計時,重新開始計時
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 進入該分支說明當前并沒有在計時,那么就開始一個計時
        }
    }
}

當然 上述代碼是為了貼合思路,方便理解(這么貼心不給個贊咩?),寫完會發(fā)現(xiàn)其實 time = setTimeOut(fn,delay)是一定會執(zhí)行的,所以可以稍微簡化下:

/*****************************簡化后的分割線 ******************************/
function debounce(fn,delay){
    let timer = null //借助閉包
    return function() {
        if(timer){
            clearTimeout(timer) 
        }
        timer = setTimeout(fn,delay) // 簡化寫法
    }
}
// 然后是舊代碼
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log("滾動條位置:" + scrollTop);
}
window.onscroll = debounce(showTop,1000) // 為了方便觀察效果我們?nèi)€大點的間斷值,實際使用根據(jù)需要來配置

此時會發(fā)現(xiàn),必須在停止?jié)L動1秒以后,才會打印出滾動條位置。

到這里,已經(jīng)把防抖實現(xiàn)了,現(xiàn)在給出定義:

對于短時間內(nèi)連續(xù)觸發(fā)的事件(上面的滾動事件),防抖的含義就是讓某個時間期限(如上面的1000毫秒)內(nèi),事件處理函數(shù)只執(zhí)行一次。

節(jié)流(throttle)

繼續(xù)思考,使用上面的防抖方案來處理問題的結(jié)果是:

如果在限定時間段內(nèi),不斷觸發(fā)滾動事件(比如某個用戶閑著無聊,按住滾動不斷的拖來拖去),只要不停止觸發(fā),理論上就永遠不會輸出當前距離頂部的距離。

但是如果產(chǎn)品同學的期望處理方案是:即使用戶不斷拖動滾動條,也能在某個時間間隔之后給出反饋呢?(此處暫且不論哪種方案更合適,既然產(chǎn)品爸爸說話了我們就先考慮怎么實現(xiàn))

其實很簡單:我們可以設(shè)計一種類似控制閥門一樣定期開放的函數(shù),也就是讓函數(shù)執(zhí)行一次后,在某個時間段內(nèi)暫時失效,過了這段時間后再重新激活(類似于技能冷卻時間)。

效果:如果短時間內(nèi)大量觸發(fā)同一事件,那么在函數(shù)執(zhí)行一次之后,該函數(shù)在指定的時間期限內(nèi)不再工作,直至過了這段時間才重新生效。

實現(xiàn) 這里借助setTimeout來做一個簡單的實現(xiàn),加上一個狀態(tài)位valid來表示當前函數(shù)是否處于工作狀態(tài):

function throttle(fn,delay){
    let valid = true
    return function() {
       if(!valid){
           //休息時間 暫不接客
           return false 
       }
       // 工作時間,執(zhí)行函數(shù)并且在間隔期內(nèi)把狀態(tài)位設(shè)為無效
        valid = false
        setTimeout(() => {
            fn()
            valid = true;
        }, delay)
    }
}
/* 請注意,節(jié)流函數(shù)并不止上面這種實現(xiàn)方案,
   例如可以完全不借助setTimeout,可以把狀態(tài)位換成時間戳,然后利用時間戳差值是否大于指定間隔時間來做判定。
   也可以直接將setTimeout的返回的標記當做判斷條件-判斷當前定時器是否存在,如果存在表示還在冷卻,并且在執(zhí)行fn之后消除定時器表示激活,原理都一樣
    */

// 以下照舊
function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log("滾動條位置:" + scrollTop);
}
window.onscroll = throttle(showTop,1000) 

運行以上代碼的結(jié)果是:

如果一直拖著滾動條進行滾動,那么會以1s的時間間隔,持續(xù)輸出當前位置和頂部的距離

其他應(yīng)用場景舉例

講完了這兩個技巧,下面介紹一下平時開發(fā)中常遇到的場景:

搜索框input事件,例如要支持輸入實時搜索可以使用節(jié)流方案(間隔一段時間就必須查詢相關(guān)內(nèi)容),或者實現(xiàn)輸入間隔大于某個值(如500ms),就當做用戶輸入完成,然后開始搜索,具體使用哪種方案要看業(yè)務(wù)需求。

頁面resize事件,常見于需要做頁面適配的時候。需要根據(jù)最終呈現(xiàn)的頁面情況進行dom渲染(這種情形一般是使用防抖,因為只需要判斷最后一次的變化情況)

思考總結(jié)

上述內(nèi)容基于防抖和節(jié)流的核心思路設(shè)計了簡單的實現(xiàn)算法,但是不代表實際的庫(例如undercore js)的源碼就直接是這樣的,最起碼的可以看出,在上述代碼實現(xiàn)中,因為showTop本身的很簡單,無需考慮作用域和參數(shù)傳遞,所以連apply都沒有用到,實際上肯定還要考慮傳遞argument以及上下文環(huán)境(畢竟apply需要用到this對象)。這里的相關(guān)知識在本專欄《柯里化》和《this對象》的文章里也有提到。本文依然堅持突出核心代碼,盡可能剝離無關(guān)功能點的思路行文因此不做贅述。

慣例:如果內(nèi)容有錯誤的地方歡迎指出(覺得看著不理解不舒服想吐槽也完全沒問題);如果有幫助,歡迎點贊和收藏,轉(zhuǎn)載請征得同意后著明出處,如果有問題也歡迎私信交流,主頁有郵箱地址

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/108989.html

相關(guān)文章

  • 前端進擊的巨人(八):淺談函數(shù)防抖節(jié)流

    摘要:隆重請出主角防抖與節(jié)流。防抖與節(jié)流的異同相同都是防止某一時間段內(nèi),函數(shù)被頻繁調(diào)用執(zhí)行,通過時間頻率控制,減少回調(diào)函數(shù)執(zhí)行次數(shù),來實現(xiàn)相關(guān)性能優(yōu)化。參考文章分鐘理解的節(jié)流防抖及使用場景函數(shù)防抖和節(jié)流 showImg(https://segmentfault.com/img/bVburM8?w=800&h=600); 本篇課題,或許早已是爛大街的解讀文章。不過春招系列面試下來,不少伙伴們還...

    _Zhao 評論0 收藏0
  • 詳談js抖和節(jié)流

    摘要:本文會分別介紹什么是防抖和節(jié)流,它們的應(yīng)用場景,和實現(xiàn)方式。防抖和節(jié)流都是為了解決短時間內(nèi)大量觸發(fā)某函數(shù)而導致的性能問題,比如觸發(fā)頻率過高導致的響應(yīng)速度跟不上觸發(fā)頻率,出現(xiàn)延遲,假死或卡頓的現(xiàn)象。 本文由小芭樂發(fā)表 0. 引入 首先舉一個例子: 模擬在輸入框輸入后做ajax查詢請求,沒有加入防抖和節(jié)流的效果,這里附上完整可執(zhí)行代碼: 沒有防抖 ...

    shevy 評論0 收藏0
  • 徹底弄懂函數(shù)抖和函數(shù)節(jié)流

    摘要:若時間差大于間隔時間,則立刻執(zhí)行一次函數(shù)。不同點函數(shù)防抖,在一段連續(xù)操作結(jié)束后,處理回調(diào),利用和實現(xiàn)。函數(shù)防抖關(guān)注一定時間連續(xù)觸發(fā)的事件只在最后執(zhí)行一次,而函數(shù)節(jié)流側(cè)重于一段時間內(nèi)只執(zhí)行一次。 原博客地址,歡迎star 函數(shù)防抖和節(jié)流 函數(shù)防抖和函數(shù)節(jié)流:優(yōu)化高頻率執(zhí)行js代碼的一種手段,js中的一些事件如瀏覽器的resize、scroll,鼠標的mousemove、mouseover...

    Mr_houzi 評論0 收藏0
  • 函數(shù)抖和節(jié)流

    摘要:應(yīng)用場景給按鈕加函數(shù)防抖防止表單多次提交。對于輸入框連續(xù)輸入進行驗證時,用函數(shù)防抖能有效減少請求次數(shù)。參考十分鐘學會防抖和節(jié)流輕松理解函數(shù)節(jié)流和函數(shù)防抖 函數(shù)防抖和節(jié)流 防抖 對于觸發(fā)非常頻繁又沒有必要每次都執(zhí)行的事件,希望合并到一次去執(zhí)行; 實現(xiàn)思路: 事件觸發(fā)后,在規(guī)定的時間范圍內(nèi)如果事件重復觸發(fā),那么忽略之前觸發(fā)的事件,并且重新開始計時,直到某一次事件觸發(fā)后大于規(guī)定時間,我們才執(zhí)...

    daydream 評論0 收藏0
  • JavaScript抖和節(jié)流

    摘要:概念函數(shù)防抖和函數(shù)節(jié)流,兩者都是優(yōu)化高頻率執(zhí)行代碼的一種手段。防抖任務(wù)頻繁觸發(fā)的情況下,只有任務(wù)觸發(fā)的間隔超過指定間隔的時候,任務(wù)才會執(zhí)行。節(jié)流指定時間間隔內(nèi)只會執(zhí)行一次任務(wù)一定時間內(nèi)方法只跑一次。 概念 函數(shù)防抖和函數(shù)節(jié)流,兩者都是優(yōu)化高頻率執(zhí)行js代碼的一種手段。 防抖:任務(wù)頻繁觸發(fā)的情況下,只有任務(wù)觸發(fā)的間隔超過指定間隔的時候,任務(wù)才會執(zhí)行。 節(jié)流:指定時間間隔內(nèi)只會執(zhí)行一次任...

    DevWiki 評論0 收藏0

發(fā)表評論

0條評論

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