1. 程式人生 > 實用技巧 >P3420 [POI2005]SKA-Piggy Banks

P3420 [POI2005]SKA-Piggy Banks

一、提出問題

  博主在開發一個app時,某個頁面可以通過輸入關鍵字顯示對應的資訊,要求使用者在輸入的過程中和輸入完成時輸入框下方都要顯示相關內容。也就是等於使用者每更改一次input框的內容就要向後端查詢一下,試想一下,如果使用者因為打錯字、或者隨意更改內容,這個過程會向後端請求多少次?

  細思極恐,於是我們需要採取一些限定手段,來減少效能消耗。也就是接下來提到的防抖和節流。

二、什麼是防抖?

  原理:第一次觸發事件時,不立即執行函式,而是給出一個限定值,在限定值內沒有再次觸發同一事件則執行函式,如果在限定值內再次觸發,則當前計時取消,重新開始計時。

  效果:如果短時間內大量觸發同一事件,只會執行一次函式。

  實現:通過setTimeout+閉包,setTimeout用於計時,閉包用來儲存時間變數

function debounce(fn,delay){
	let timer = null 
				
	return function(){

		if(timer){
			clearTimeout(timer)
		}
					
		timer = setTimeout(fn,delay)
	}
}

三、什麼是節流 

  原理:第一次觸發事件時,執行對應的函式,並設定時間戳,再次觸發事件時核驗兩次事件的觸發間隔是否超過限定值,沒有超過則不予執行,超過才執行

  效果:如果短時間內大量觸發同一事件,那麼在函式執行一次之後,該函式在指定的時間期限內不再工作,直至過了這段時間才重新生效。

  實現:時間戳+定時器

function throttle(func, delay) {
    var timer = null; // 使用閉包,快取變數
    var prev = Date.now(); // 最開始進入滾動的時間
    return function() {
      var context = this;   // this指向window
      var args = arguments;
      var now = Date.now();
      var remain = delay - (now - prev); // 剩餘時間
      clearTimeout(timer);
      // 如果剩餘時間小於0,就立刻執行
      if (remain <= 0) {
        func.apply(context, args);
        prev = Date.now();
      } else {
        timer = setTimeout(func, remain);
      }
    }
  }

  在節流函式內部使用開始時間prev、當前時間now和剩餘時間remain,當剩餘時間小於等於0意味著執行處理函式,這樣保證第一次就能立即執行函式並且每隔delay時間執行一次; 如果還沒到時間,就會在remaining之後觸發,保證最後一次觸發事件也能執行函式,如果在remaining時間內又觸發了滾動事件,那麼會取消當前的計數器並計算出新的remaing時間。

四、區別以及應用場景

  1.區別

    函式防抖和函式節流都是防止某一事件頻繁觸發,但是這兩兄弟之間的原理卻不一樣。 防抖是將多次執行變為只執行一次,節流是將多次執行變為每隔一段時間執行。

  2.應用場景

    (1)防抖

      search搜尋聯想,使用者在不斷輸入值時,用防抖來節約請求資源。

      window觸發resize的時候,不斷的調整瀏覽器視窗大小會不斷的觸發這個事件,用防抖來讓其只觸發一次

      登入、發簡訊等按鈕避免使用者點選太快,以致於傳送了多次請求,需要防抖

      文字編輯器實時儲存,當無任何更改操作一秒後進行儲存

    (2)節流

      滑鼠不斷點選觸發,mousedown(單位時間內只觸發一次)

      監聽滾動事件,比如是否滑到底部自動載入更多,用throttle來判斷

參考:https://www.cnblogs.com/ympjsc/p/11813691.html

   https://www.cnblogs.com/momo798/p/9177767.html

   https://segmentfault.com/a/1190000018428170