問問自己,你真的會用防抖和節流麽????

来源:https://www.cnblogs.com/xiao-yaolx/archive/2019/12/26/12101939.html
-Advertisement-
Play Games

今天在改一個看似很簡單以前也經常遇到的一個bug發現了很多問題。實際結果肯定沒有想象的那麼簡單。所以我想總結一下:保證下次不會踩坑。 業務場景是點擊一個按鈕,會產生一個彈框。重覆快速的點擊多次,會產生多個彈框。那麼這個問題該怎麼解決呢? 1. 函數防抖節流 這兩個東西我不知道看過了多少文檔,可到現在 ...


今天在改一個看似很簡單以前也經常遇到的一個bug發現了很多問題。
實際結果肯定沒有想象的那麼簡單。所以我想總結一下:保證下次不會踩坑。
---
業務場景是點擊一個按鈕,會產生一個彈框。重覆快速的點擊多次,會產生多個彈框。
那麼這個問題該怎麼解決呢?

1. 函數防抖節流
這兩個東西我不知道看過了多少文檔,可到現在掌握的還是不夠好。
所以今天我想趁熱打鐵一波,把他們徹徹底底給搞明白!

防抖:什麼是防抖呢? 就是比如你規定一段延時 時間,在這段時間內你持續觸發這個事件,事件處理函數才會執行一次,如果設定的時間到來之前,你又觸發了一次事件,就重新開始延時。 來個圖更加形象!



//接著肯定就是實現防抖的代碼了
//防抖
function debounce(fn,wait) {
var timeout = null;
return function() {
if(timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn,wait)
}
}
//處理函數
function handle() {
console.log(Math.random())
}
//滾動事件
window.addEventListener('scroll',debounce(handle,1000))

當持續觸發scroll事件時,事件處理函數handle只在停止滾動1000毫秒之後才會調用一次,也就是說在持續觸發scroll事件的過程中,事件處理函數handle一直沒有執行。

節流:那麼什麼是節流呢?認識了防抖之後一定不要混淆了節流的概念,我之前就是犯這個錯誤。
言歸正傳,節流就是當你持續觸發事件時,保證一段時間內只調用一次事件的處理函數,通俗點說就比如我們水龍頭放水,閥門一打開,水嘩嘩的往下流,秉著勤儉節約的優良傳統美德,我們要把水龍頭關小點,最好是如我們心意按照一定規律在某個時間間隔內一滴一滴的往下滴。如下圖,持續觸發scroll事件時,並不立即執行handle函數,每隔1000毫秒才會執行一次handle函數。


函數節流主要有兩種實現方法:時間戳和定時器。接下來分別用兩種方法實現throttle~

//節流函數(時間戳)
function throttle(fn, delay) {
//記錄第一次執行時的時間
var prev = Date.now()
return function() {
var contxt = this
var args = arguments
var now = Date.now()
//如果當前時間減去上一次執行的時間大於等於延時時間
if(now -prev >= delay) {
//執行
fn.apply(contxt, args)
//執行後的時間
prev = Date.now()
}
}
}
//處理函數
function handle() {
console.log(Math.random())
}
//滾動事件
window.addEventListener('scroll',throttle(handle,1000))
```
```javascript
//節流函數(定時器)
function throttle(fn, delay) {
var timer = null
return function() {
var contxt = this
var args = arguments
//如果定時器不存在
if(!timer) {
timer = setTimeout(function(){
fn.apply(contxt,args)
timer = null
},delay)
}
}
}
//處理函數
function handle() {
console.log(Math.random())
}
//滾動事件
window.addEventListener('scroll',throttle(handle,1000))

當觸發事件的時候,我們設置一個定時器,再次觸發事件的時候,如果定時器存在,就不執行,直到delay時間後,定時器執行執行函數,並且清空定時器,這樣就可以設置下個定時器。當第一次觸發事件時,不會立即執行函數,而是在delay秒後才執行。而後再怎麼頻繁觸發事件,也都是每delay時間才執行一次。當最後一次停止觸發後,由於定時器的delay延遲,可能還會執行一次函數。

節流中用時間戳或定時器都是可以的。更精確地,可以用時間戳+定時器,當第一次觸發事件時馬上執行事件處理函數,最後一次觸發事件後也還會執行一次事件處理函數。

// 節流throttle代碼(時間戳+定時器):
var throttle = function(func, delay) { 
var timer = null; 
var startTime = Date.now(); 
return function() { 
var curTime = Date.now(); 
var remaining = delay - (curTime - startTime); 
var context = this; 
var args = arguments; 
clearTimeout(timer); 
if (remaining <= 0) { 
func.apply(context, args); 
startTime = Date.now(); 
} else { 
timer = setTimeout(func, remaining); 
} 
}
}
function handle() { 
console.log(Math.random());
} 
window.addEventListener('scroll', throttle(handle, 1000));

總結:

函數防抖:將幾次操作合併為一此操作進行。原理是維護一個計時器,規定在delay時間後觸發函數,但是在delay時間內再次觸發的話,就會取消之前的計時器而重新設置。這樣一來,只有最後一次操作能被觸發。

函數節流:使得一定時間內只觸發一次函數。原理是通過判斷是否到達一定時間來觸發函數。

區別: 函數節流不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次真正的事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。 比如在頁面的無限載入場景下,我們需要用戶在滾動頁面時,每隔一段時間發一次 Ajax 請求,而不是在用戶停下滾動頁面操作時才去請求數據。這樣的場景,就適合用節流技術來實現。

今天本想用其中一種方法解決我前面提到的業務場景,可萬萬沒想到的是,兩種方法我試了,都不行,可能是微信小程式的機制和PC端不同的緣故吧,所以最後 我採用了遮罩層的方法實現。
就是在他第一次點擊的時候就設置一個遮罩層,不讓他點擊了,不就成功解決了這個問題了麽???


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、解決:每次都需要輸入賬號密碼 git config --global credential.helper store 二、後期git密碼更改後,重置密碼操作 git config --system --unset credential.helper ...
  • 一、es6 Set去重 function removal(arr) { return Array.from(new Set(arr)) } let arr=[1,2,1,3,4,5,5] removal(arr)//[1, 2, 3, 4] 二、利用 filter function removal( ...
  • 1 在JavaScript中的變數分別區分為兩種: 一種為基本類型值,一種為應用類型值。 基本類型值指的是簡單的數據段 引用類型值為可能由多個值組成的對象 引用類型的值是保存在記憶體中的對象,JavaScript不允許直接操作對象的記憶體空間,實際上操作對象的引用而不是實際對象。 var dada = ...
  • 一、左右兩列佈局 1、代碼如下,可先粘貼複製,自行運行 <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>兩列佈局</title><!--左邊列固定,右邊列自適應--> <style type="text/css"> *{ padd ...
  • JavaScript高級函數 1.map/reduce map() map()是array的一個方法 作用: 對array中每一個元素調用自定義函數 map的回調函數有三個參數: callback(currentValue, index, array) 通常只要第一個參數 PS: map()傳入的參 ...
  • 在前端開發過程中,非IE瀏覽器下,當容器的高度自動,並且容器內容中有浮動元素(float為left或right),此時如果容器的高度不能自適應內容的高度,從而使得內容溢出破壞整體佈局,這種現象叫做浮動溢出,為了方式這個現象的發生,就需要對CSS樣式進行處理,而這個過程就叫做CSS清除浮動。現在常用的 ...
  • <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...