前端函數防抖(Debounce)完整講解 - 從原理、應用到完整實現

在這里插入圖片描述

🌷 古之立大事者,不惟有超世之才,亦必有堅忍不拔之志
🎐 個人CSND主頁——Micro麥可樂的博客
🐥《Docker實操教程》專欄以最新的Centos版本為基礎進行Docker實操教程,入門到實戰
🌺《RabbitMQ》專欄19年編寫主要介紹使用JAVA開發RabbitMQ的系列教程,從基礎知識到項目實戰
🌸《設計模式》專欄以實際的生活場景為案例進行講解,讓大家對設計模式有一個更清晰的理解
🌛《開源項目》本專欄主要介紹目前熱門的開源項目,帶大家快速了解并輕松上手使用
?《開發技巧》本專欄包含了各種系統的設計原理以及注意事項,并分享一些日常開發的功能小技巧
💕《Jenkins實戰》專欄主要介紹Jenkins+Docker的實戰教程,讓你快速掌握項目CI/CD,是2024年最新的實戰教程
🌞《Spring Boot》專欄主要介紹我們日常工作項目中經常應用到的功能以及技巧,代碼樣例完整
🌞《Spring Security》專欄中我們將逐步深入Spring Security的各個技術細節,帶你從入門到精通,全面掌握這一安全技術
如果文章能夠給大家帶來一定的幫助!歡迎關注、評論互動~

前端函數防抖(Debounce)完整講解 - 從原理、應用到完整實現

  • 1. 前言
  • 2. 為什么使用防抖?
  • 3. 函數防抖的應用場景
  • 4. 完整代碼實現
    • ? 基礎防抖函數
    • ? 使用示例(輸入框搜索)
    • ? React Hooks 防抖實現
    • ? 使用 Lodash 的 _.debounce
  • 5. 高階技巧與注意事項
  • 6. 結語

1. 前言

在我們日常前端開發中,高頻觸發的事件(如輸入框輸入、窗口縮放、滾動事件)可能導致性能問題甚至引發BUG。函數防抖(debounce)是一種常見且高效的性能優化手段,用于限制高頻事件觸發下的函數調用次數,從而減少不必要的計算、網絡請求或 DOM 操作。

本文博主將帶著小伙伴一起深入解析防抖機制的原理、六大應用場景,并提供可直接復用的代碼示例。


2. 為什么使用防抖?

在這里插入圖片描述
我們來看看你是否也遇到這樣的問題:

當用戶快速連續觸發事件時,例如:

  • 搜索框每輸入一個字符立即請求接口
  • 窗口縮放時頻繁更新布局
  • 瘋狂點擊提交按鈕

會導致:

  • 性能浪費:不必要的計算/請求
  • 數據錯亂:異步請求響應順序不可控
  • 用戶體驗差:界面卡頓或閃爍

函數防抖的核心思想是在連續觸發的事件停止后,僅執行最后一次調用,以避免頻繁觸發帶來的性能問題。
延遲執行 + 重置計時器:在事件被觸發后等待指定時間(如300ms),若期間沒有再次觸發,則執行函數;若期間重復觸發,則重新開始計時


3. 函數防抖的應用場景

場景示例解決方案
搜索建議輸入框聯想詞查詢停止輸入300ms后發起請求
按鈕提交防止重復提交訂單點擊后禁用按鈕直至操作完成
窗口調整響應式布局計算窗口停止調整后執行計算
滾動加載無限滾動加載更多停止滾動后觸發檢測
畫布繪制實時預覽圖形渲染停止拖拽后更新渲染
表單驗證密碼強度實時檢測輸入結束再進行復雜校驗

為了讓大家更清晰了解其應用場景,我們例舉幾個說明:

1、輸入框實時搜索
在用戶輸入關鍵詞時觸發搜索接口,若不加限制,每次 keyup 都會發起請求,極易導致接口壓力過大。使用防抖后,只在用戶停止輸入(如 300ms)后才發送請求,有效降低調用次數

2、按鈕防連點
對于提交表單或支付按鈕,連續點擊可能導致多次提交。給點擊事件綁定防抖函數,可在用戶短時間內多次點擊時只執行一次提交操作

3、窗口大小調整(resize)
當頁面布局需根據窗口大小實時計算或重繪時,resize 事件會頻繁觸發,添加防抖能減少重繪次數,提升性能

4、滾動監聽
結合無限滾動或懶加載,當用戶滾動頁面時應控制數據加載頻率,避免重復請求或過度渲染


4. 完整代碼實現

防抖函數通過內部維護一個定時器 ID,每次調用時先清除之前的定時器,再啟動一個新的延遲執行定時器;只有在最后一次調用后的延遲時間到達后,才真正執行目標函數

? 基礎防抖函數

先看一個簡單實現:

/*** 防抖函數* @param {Function} fn  需要防抖的函數* @param {number} delay 延遲時間(毫秒)* @returns {Function}    包裝后的防抖函數*/
function debounce(fn, delay = 300) {let timer = nullreturn function(...args) {// 每次觸發時清除之前的計時器if (timer) clearTimeout(timer)// 設置新的計時器timer = setTimeout(() => {fn.apply(this, args)  // 確保正確的this上下文timer = null}, delay)}
}

上述代碼利用 JavaScript 閉包,讓每個防抖函數維護獨立的 timeoutId,在多次調用時只有最后一次延遲結束后觸發

? 使用示例(輸入框搜索)

<input type="text" id="searchInput"><script>
const searchInput = document.getElementById('searchInput')// 原始請求函數
function fetchSearchResult(keyword) {console.log(`搜索關鍵詞: ${keyword}`)// 實際調用API接口...
}// 包裝為防抖版本(500ms延遲)
const debouncedFetch = debounce(fetchSearchResult, 500)// 綁定輸入事件
searchInput.addEventListener('input', (e) => {debouncedFetch(e.target.value.trim())
})
</script>

? React Hooks 防抖實現

import { useCallback, useEffect, useRef } from 'react'// 自定義防抖Hook
function useDebounce(fn, delay) {const timerRef = useRef(null)const debouncedFn = useCallback((...args) => {if (timerRef.current) clearTimeout(timerRef.current)timerRef.current = setTimeout(() => {fn(...args)timerRef.current = null}, delay)}, [fn, delay])// 組件卸載時清除計時器useEffect(() => {return () => {if (timerRef.current) clearTimeout(timerRef.current)}}, [])return debouncedFn
}// 在組件中使用
function SearchBox() {const [keyword, setKeyword] = useState('')// 防抖請求函數const debouncedSearch = useDebounce((value) => {console.log('實際搜索:', value)}, 500)const handleChange = (e) => {setKeyword(e.target.value)debouncedSearch(e.target.value)}return <input value={keyword} onChange={handleChange} />
}

? 使用 Lodash 的 _.debounce

在實際項目中,為了減少手寫錯誤并獲得更豐富的功能(如 leading、trailing、cancel、flush 等選項),推薦使用成熟的工具庫 Lodash_.debounce 方法

# 安裝 lodash.debounce 子模塊
npm install lodash.debounce

快速使用:

import debounce from 'lodash.debounce';/** * 在搜索框中使用防抖 * 當用戶停止輸入 300ms 后才觸發搜索 */
const searchInput = document.getElementById('search');
function onSearch(query) {// 發送搜索請求console.log('搜索關鍵詞:', query);
}
const debouncedSearch = debounce(onSearch, 300, { leading: false, trailing: true });searchInput.addEventListener('input', (e) => {debouncedSearch(e.target.value);
});

參數說明

  • leading: 是否在延遲開始前調用一次,默認 false。
  • trailing: 是否在延遲結束后調用一次,默認 true。
  • 返回的函數還擁有 cancel() 和 flush() 方法,可在需要時取消或立即執行待定調用

5. 高階技巧與注意事項

  1. 立即執行模式
    在不使用Lodash庫時,我們也可以添加立即執行選項,首次觸發立即執行,后續觸發進入防抖

    function debounce(fn, delay, immediate = false) {let timerreturn function(...args) {if (immediate && !timer) fn.apply(this, args)if (timer) clearTimeout(timer)timer = setTimeout(() => {if (!immediate) fn.apply(this, args)timer = null}, delay)}
    }
    
  2. 防抖與節流區別

    • 防抖(Debounce):等電梯(最后一個人進來后等10秒關門)
    • 節流(Throttle):發短信(每60秒只能發一次)
  3. 性能優化

    • 高頻事件(如mousemove)建議結合requestAnimationFrame
    • 避免在防抖函數中處理大型對象

6. 結語

函數防抖是前端性能優化中的一項基礎技術,適用于各種需要限制高頻事件調用的場景,通過本文介紹的 定時器邏輯 或成熟的 Lodash 工具庫,就能快速落地。通過本文的代碼示例,小伙伴們可以快速將其應用到實際項目中。當遇到高頻觸發事件時,不妨先思考:這個場景是否需要防抖?

如果你在實踐過程中有任何疑問或更好的擴展思路,歡迎在評論區留言,最后希望大家 一鍵三連 給博主一點點鼓勵!


前端技術專欄回顧:

01【前端技術】 ES6 介紹及常用語法說明
02【前端技術】標簽頁通訊localStorage、BroadcastChannel、SharedWorker的技術詳解
03 前端請求亂序問題分析與AbortController、async/await、Promise.all等解決方案
04 前端開發中深拷貝的循環引用問題:從問題復現到完美解決
05 前端AJAX請求上傳下載進度監控指南詳解與完整代碼示例
06 TypeScript 進階指南 - 使用泛型與keyof約束參數
07 前端實現視頻文件動畫幀圖片提取全攻略 - 附完整代碼樣例
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/906642.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906642.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906642.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服務接口鑒權與內部認證:自定義注解與AOP實現的企業級實踐

本文深入解析企業級系統中接口安全管控的核心需求&#xff0c;提出基于Spring AOP與自定義注解的輕量級鑒權方案。通過解構注解元數據定義、切面攔截邏輯、上下文傳遞機制等關鍵技術環節&#xff0c;系統闡述零侵入式鑒權體系的構建路徑。結合金融支付網關、多租戶SaaS平臺、物…

26考研|高等代數:線性變換

前言 線性變換這一章節是考頻較高的一部分&#xff0c;此部分涉及考點較多&#xff0c;涉及的考題也較多&#xff0c;學習線性變換時&#xff0c;應該注意搭建線性變換與矩陣之間的聯系&#xff0c;掌握如何利用矩陣表示一個線性變換結構&#xff0c;同時介紹了最簡單的線性變…

電磁兼容(EMC)仿真(精編版)

寫在前面 本系列文章主要講解電磁兼容(EMC)仿真的相關知識,希望能幫助更多的同學認識和了解電磁兼容(EMC)仿真。 若有相關問題,歡迎評論溝通,共同進步。(*^▽^*) 隨著產品復雜性和密集度的提高以及設計周期的不斷縮短,在設計周期的后期解決電磁兼容性(EMC)問題變得…

解決:dpkg: error: dpkg frontend lock is locked by another process

1、等待其他進程完成 如果后臺有其他包管理操作&#xff08;如自動更新、軟件安裝等&#xff09;&#xff0c;等待幾分鐘再重試。 可以通過以下命令查看是否有相關進程&#xff1a; ps aux | grep -E apt|apt-get|dpkg 2、強制終止占用鎖的進程 如果確認沒有其他包管理操作&…

LVGL(lv_textarea文本框控件)

文章目錄 一、lv_textarea 是什么&#xff1f;二、基本用法1. 創建 lv_textarea 對象2. 設置提示文字&#xff08;占位符&#xff09;3. 設置最大長度4. 設置密碼模式&#xff08;顯示為\*號&#xff09;5. 獲取和設置內容6. 配合虛擬鍵盤使用&#xff08;常用于觸摸屏&#xf…

【Java高階面經:數據庫篇】18、分布式事務:如何在分庫分表中實現高性能與一致性?

一、分布式事務核心挑戰:分庫分表下的一致性困境 在分布式系統架構中,分庫分表通過將數據分散存儲提升了擴展性和性能,但卻打破了傳統單庫事務的邊界,使得分布式事務成為保障數據一致性的核心難題。其挑戰主要體現在以下三方面: 1.1 ACID特性的分布式撕裂 原子性(Atomi…

【云吶】房地產企業固定資產如何管理

房產類固定資產如辦公樓、門面房、宿舍樓、庫房等&#xff0c;價值高、使用年限長、權屬復雜、變更流程多&#xff0c;是企業最為關鍵的資產類型之一。管理房產類資產不僅要“看得到”&#xff0c;更要“管得住”。 房產資產管理應從權屬明確開始。固定資產管理系統支持房產資產…

oracle數據庫生成awr報告,排查數據庫服務器CPU100%,系統卡頓,慢sql,根據sqlid查詢關鍵信息,如會話SID,客戶端機器名

AWR報告簡介 AWR是Oracle 10g版本推出的特性,全稱叫做 Automatic Workload Repository 全自動負載信息庫 。Oracle啟動后,會有后臺進程定時采集并保存系統快照信息,也可以手工創建快照。AWR通過對比兩個時間點的快照信息,生成該時間段的AWR報告,幫助DBA或開發人員了解 Ora…

kafka吞吐量提升總結

前言 原本自以為閱讀了很久kafka的源碼&#xff0c;對于kafka的了解已經深入到一定程度了&#xff0c;后面在某大廠的面試中&#xff0c;面試官詢問我&#xff0c;如果需要提升kafka的性能&#xff0c;應該怎么做&#xff0c;我發現我能答上來的點非常的少&#xff0c;也暴露了…

鴻蒙 HarmonyOS NEXT 系統 Preference 首選項使用全解析

鴻蒙HarmonyOS系統Preference首選項使用全解析 大家好&#xff0c;我是威哥。在鴻蒙應用開發里&#xff0c;用戶偏好設置的管理是極為重要的一環。HarmonyOS為我們提供了Preference組件&#xff0c;它能讓我們輕松實現應用設置界面&#xff0c;對用戶首選項進行高效管理。接下…

xdc約束學習

對clk的約束 //約束clk為 125M Hz create_clock -period 8.000 -name gt_refclk1_p -waveform {0.000 4.000} [get_ports gt_refclk1_p] 偽時鐘路徑&#xff0c;用于兩個時鐘域之間數據的交互 單邊性&#xff08;unateness&#xff09;對于時序很重要&#xff0c;因為它指定的…

在 Ubuntu 虛擬機中實現 HTML 表單與 C 語言 HTTP 服務器交互

一、環境說明 系統&#xff1a;Ubuntu 虛擬機&#xff08;已安裝基本開發工具&#xff0c;如 GCC&#xff09;目標&#xff1a;通過 C 語言服務器托管 HTML 表單頁面&#xff0c;并實現數據提交交互 二、核心文件準備 1. 創建 HTML 表單頁面&#xff08;xunfei.html&#xf…

LVS 負載均衡集群應用實戰

前提:三臺虛擬機,有nginx,要做負載 1. LVS-server 安裝lvs管理軟件 [root@lvs-server ~]# yum -y install ipvsadm 程序包:ipvsadm(LVS管理工具) 主程序:/usr/sbin/ipvsadm 規則保存工具:/usr/sbin/ipvsadm-save > /path/to/file 配置文件:/etc/sysconfig/ipvsad…

鴻蒙進階——Framework之Want 隱式匹配機制概述

文章大綱 引言一、Want概述二、Want的類型1、顯式Want2、隱式Want3、隱式Want的匹配 三、隱式啟動Want 源碼概述1、有且僅有一個Ability匹配2、有多個Ability 匹配需要彈出選擇對話框3、ImplicitStartProcessor::ImplicitStartAbility3.1、GenerateAbilityRequestByAction3.1.1…

Rules and Monetization

The system creates rules that allow them to monetize. The system doesn’t just enforce rules — it creates them strategically to monetize control. &#x1f527; How It Works: Invent a rule (e.g., “You need a permit to sell food.”)Claim it’s for safety …

java中string類型的list集合放到redis的5種數據類型的那種比較合適呢,可以用StringRedisTemplate實現

在Java中&#xff0c;如何將一個String類型的List集合存儲到Redis中&#xff0c;并且應該選擇Redis的哪種數據類型。同時&#xff0c;用戶還問到是否可以使用StringRedisTemplate來實現。 首先&#xff0c;我需要回憶一下Redis的5種主要數據類型&#xff1a;字符串&#xff08;…

基于DQN的學習資源難度匹配智能體

基于DQN的學習資源難度匹配智能體 下面我將實現一個基于DQN(深度Q網絡)的智能體,用于根據用戶的學習表現動態匹配適合難度的學習資源。這個系統可以應用于在線教育平臺,根據用戶的歷史表現自動調整推薦資源的難度級別。 1. 環境設置 首先我們需要定義學習環境,這里我創建…

OrangePi Zero2開發指南:從SDK獲取到交叉編譯全流程詳解

一、OrangePi Zero2 SDK說明 SDK 全稱 Software Development Kit&#xff0c;即軟件開發工具包。一般包括了一些工具&#xff08;如交叉編譯工具鏈&#xff09;、庫、文檔和示例代碼。香橙派的Linux SDK其實指的就是 orangepi-build 這套代碼集&#xff0c;orangepibuild 在腳…

MATLAB NLP 工具箱 文本預處理教程

文章目錄 前言一、文本預處理核心步驟二、MATLAB 實現示例三、高級預處理技術四、預處理流程整合五、性能優化與注意事項六、實戰案例&#xff1a;IMDB 影評預處理 前言 以下是 MATLAB 自然語言處理 (NLP) 工具箱的文本預處理教程&#xff0c;涵蓋核心步驟、代碼實現及最佳實踐…

大模型的量化與雙重量化(1)

文章目錄 大模型量化的含義和作用什么是量化量化的作用具體示例 雙重量化的含義和作用什么是雙重量化雙重量化的具體實現雙重量化的作用具體示例對比實際應用場景 大模型量化的含義和作用 什么是量化 量化是指將神經網絡中的參數&#xff08;權重和激活值&#xff09;從高精度…