防抖與節流的封裝函數與使用詳解

防抖與節流

爲什麼使用防抖節流?
在前端開發中有一部分的用戶行爲會頻繁的觸發事件執行,而對於DOM操作、資源加載等耗費性能的處理,很可能導致界面卡頓,甚至瀏覽器的崩潰。函數節流(throttle)和函數防抖(debounce)就是爲了解決類似需求應運而生的。

防抖(debounce)

函數防抖就是在函數需要頻繁觸發情況時,只有足夠空閒的時間,才執行一次。好像公交司機會等人都上車後才關門一樣。他不會上來一個人就觸發一次關門,而是等人陸續上來後等待一會再觸發關門

場景:(當時間頻繁觸發後停止一段時間執行)

  • 實時搜索(keyup)
  • 拖拽( mousemove )
  • 手機號、郵箱驗證輸入檢測
  • 窗口大小Resize。只需窗口調整完成後,計算窗口大小。防止重複渲染。

我們以百度搜索框在輸入完成後停頓一段時間便會進ajax請求爲例子,我們實現輸入框停止輸入後再打印

//使用高階函數,利用閉包封裝
    <!-- <script src="../../plugin/helpers.js"></script> -->
   
        let oInp = document.getElementById('inp')
        let timer = null
        const debounce = (handler, delay) => {
            let timer = null //利用閉包保存同一個timer
            return () => {
                let _self = this //取debounce執行作用域的this
                let _arg = arguments //利用閉包保存參數數組
                clearTimeout(timer) //不斷的執行函數不斷的清除定時器
                timer = setTimeout(() => {
                    handler.apply(_self, _arg) //用apply指向調用debounce的對象,相當於_this.handler(args);
                }, delay)
            }
        }
        let shouValue = (e) => {
            console.log(e,this.value)
        }
        oInp.oninput = debounce(shouValue, 1000);

節流(throttle)

函數節流就是預定一個函數只有在大於等於執行週期時才執行,週期內調用不執行。好像水滴攢到一定重量纔會落下一樣。

場景: CON(不管時間觸發的多麼頻繁,至少要每隔一段時間執行而不是等事件觸發完了等一段時間執行)

窗口調整(resize)
頁面滾動( scroll)
搶購瘋狂點擊( mousedown)

目前我有兩種思路:

  • 使用定時器,定時一秒鐘之後去執行,但是在這1s中不停的調用,不讓他的定時器清零重新計時,不會影響當前的結果,還是那1s繼續等,等1秒時觸發(會出現停止操作還是會觸發)
//保證一個時間段內執行一次
        const throttle = (handler, time) => {
            let timer
            return () => {
                if (timer) {
                    return //判斷如果有計時器不清零直接返回啥也不做
                }
                let _self = this //取throttle 執行作用域的this
                let _arg = arguments //利用閉包保存參數數組
                timer = setTimeout(() => {
                    handle.apply(_self, _arg)
                    timer = null
                }, time)
            }
        }
        //觸發事件
        window.onresize =  () => handle()
        //處理函數
        let test = () =>console.log("a")
        //調用throttle函數傳參
        let handle = myPlugin.throttle(test, 2000)
  • 使用時間戳,先立即執行,只不過在下一次執行要等一段時間
 const throttle = (handler, time) => {
            let t 
            return () => {
                let _self = this //取throttle 執行作用域的this
                let _arg = arguments //利用閉包保存參數數組
                if (!t || Date.now() - t >= time ) {
                    handler.apply(_self , _arg );
                    t = Date.now(); //得到的當前時間戳
                }
            }
        }
        window.onresize =  () => handle()
        let test = () =>console.log("a")
        let handle = myPlugin.throttle(test, 2000)

判斷兩種方式差異,我們只需要判斷是否需要立即執行,我們就可以把節流的兩種合併在一起

//保證一段時間只執行一次
      constthrottle = (handler, time, immediately) => {
            if (immediately === undefined) {
                immediately = true //判斷需要先立即執行
            }
            if (immediately) {
                let t
                return () => {
                    let _self = this //取throttle 執行作用域的this
                    let _arg = arguments //利用閉包保存參數數組
                    if (!t || Date.now() - t >= time) {
                        handler.apply(_self, _arg);
                        t = Date.now(); //得到的當前時間戳
                    }
                }
            }
            else {
                let timer
                return () => {
                    if (timer) {
                        return //判斷如果有計時器不清零直接返回啥也不做
                    }
                    let _self = this //取throttle 執行作用域的this
                    let _arg = arguments //利用閉包保存參數數組
                    timer = setTimeout(() => {
                        handle.apply(_self, _arg)
                        timer = null
                    }, time)
                }
            }

        }
        window.onresize = () => handle()
        let test = () => console.log("a")
        let handle = myPlugin.throttle(test, 2000,true)

tip:>(免費獲取最新完整前端課程關注vx公衆號:前端拓路者coder,回覆:資料
如果這個文章對你有用的話,歡迎點贊轉發關注,讓更多的小夥伴看到呀,畢竟分享是一個程序員最基本的美德!!!
如果有不對的請大佬指教)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章