控制事件觸發(fā)頻率的兩種策略:Debounce && Throttle

為什么要使用這兩種策略

在我們?nèi)粘5拈_發(fā)中,以下幾種情況會(huì)高頻率的觸發(fā)事件:

  • resize
  • scroll
  • click
  • mousemove
  • keydown

高頻率的觸發(fā)事件,會(huì)過度損耗頁面性能,導(dǎo)致頁面卡頓,頁面抖動(dòng),尤其是當(dāng)這些事件回調(diào)函數(shù)中包含ajax等異步操作的時(shí)候,多次觸發(fā)會(huì)導(dǎo)致返回的內(nèi)容結(jié)果順序不一致,而導(dǎo)致得到的結(jié)果非最后一次觸發(fā)事件對應(yīng)的結(jié)果。

兩種策略的工作方式

Debounce:一部電梯停在某一個(gè)樓層,當(dāng)有一個(gè)人進(jìn)來后,20秒后自動(dòng)關(guān)門,這20秒的等待期間,又一個(gè)人按了電梯進(jìn)來,這20秒又重新計(jì)算,直到電梯關(guān)門那一刻才算是響應(yīng)了事件。

Throttle:好比一臺自動(dòng)的飲料機(jī),按拿鐵按鈕,在出飲料的過程中,不管按多少這個(gè)按鈕,都不會(huì)連續(xù)出飲料,中間按鈕的響應(yīng)會(huì)被忽略,必須要等這一杯的容量全部出完之后,再按拿鐵按鈕才會(huì)出下一杯。

使用方式

這里我們使用 Lodash 庫里面實(shí)現(xiàn)的debouce和throttle方法。
lodash支持自定義封裝,使用下面兩個(gè)命令封裝一個(gè)我們自己的lodash庫。

$ npm i -g lodash-cli
$ lodash include=debouce,throttle

debounce調(diào)用方法:_.debounce(func, [wait=0], [options={}]) 返回一個(gè)具有debounce策略的新函數(shù)。
throttle調(diào)用方法:_.throttle(func, [wait=0], [options={}]) 返回一個(gè)具有throttle策略的新函數(shù)。

debounce參數(shù)列表

func (Function): The function to debounce.
[wait=0] (number): The number of milliseconds to delay.
[options={}] (Object): The options object.
[options.leading=false] (boolean): Specify invoking on the leading edge of the timeout.
[options.maxWait] (number): The maximum time func is allowed to be delayed before it's invoked.
[options.trailing=true] (boolean): Specify invoking on the trailing edge of the timeout.

下面的例子是在移動(dòng)端使用 rem 布局常用的一個(gè)函數(shù),偵聽resize事件改變根元素的fontSize,這種情況下適用debounce策略:

;(function (win, doc) {
      let docEl = doc.documentElement;
      const psdWidth = 750,
            psdHeight = 1200,
            aspect = psdWidth / psdHeight;

      const recalc = function() {
          const clientWidth = docEl.clientWidth;
          const clientHeight = docEl.clientHeight;
          
          if (!clientWidth) return;
          if((clientWidth / clientHeight) > aspect) {
            let ratio = clientWidth / psdWidth;
            docEl.style.fontSize = 100 * ratio + 'px';
          } else {
            let ratio = clientHeight / psdHeight;
            docEl.style.fontSize = 100 * ratio + 'px';
          }
        };

      if (!doc.addEventListener) return;

      const debounceRecalc = _.debounce(recalc, 200, {});
      win.addEventListener('resize', debounceRecalc, false);
      win.addEventListener('orientationchange', debounceRecalc, false);
      debounceRecalc();
    })(window, document)

這個(gè)例子中,使用throttle策略,點(diǎn)擊一次生成一行文字,1s中無論怎么點(diǎn)擊,都只生成一行文字:

   ;(function(){
        let throttleBtn = document.querySelector('.throttle-click');
        let text = document.querySelector('.show-text');

        let clickHandler = _.throttle(function (){
            text.innerHTML += '<p>do it.</p>';
            console.log('do it.')
        }, 1000, {});

      throttleBtn.addEventListener('click', clickHandler);
    })();

完整demo地址:demo

實(shí)現(xiàn)源代碼

debounce.js
throttle.js

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,173評論 0 29
  • 1 概念 首先講講關(guān)注函數(shù)節(jié)流這個(gè)概念的原因~~,其實(shí)還是因?yàn)闃I(yè)務(wù)驅(qū)動(dòng),在實(shí)現(xiàn)無限加載組件(就是滾動(dòng)到底部,就可以...
    Coder_不易閱讀 2,606評論 1 3
  • 這個(gè)世界沒有所謂的安逸與舒服,除非你是死人,這樣就永遠(yuǎn)不會(huì)為了明天而活。 在工作中遇到的困難只能是你拿的這份工資對...
    夏至若離閱讀 570評論 0 0
  • 渡江云.會(huì)澤贊曲 徐 宏 以禮河畔柳色新,梯極發(fā)電萬家明。會(huì)澤古城,‘’錢王之鄉(xiāng)‘’美名傳...
    sunxuhong閱讀 539評論 0 2

友情鏈接更多精彩內(nèi)容