前端防抖-vue3原生实现、使用第三方库 Lodash实现

vue3 原生实现防抖

优点:实现简单,适合简单场景

例子:输入姓名、关键词延时搜索,操作更新后的DOM

watch实现

HTML代码:

<template>
  <input v-model="name" ref="inputEl" />
  <input v-model="searchKeyword" ref="inputEl" />
</template>

TS 代码

<script setup lang="ts">
import { ref, watchEffect, watchPostEffect } from 'vue'
const name = ref('')
const searchKeyword = ref('')

watch(
  [name, searchKeyword],
  (newValue, oldValue, cleanup) => {
    let timer = setTimeout(() => {
      console.log("设置定时")
      doSearch() // 执行搜索
    }, 500)
    cleanup(() => {
      console.log("清除定时")
      clearTimeout(timer)
    })
  },
  { deep: true }
)
</script>

watchEffect实现

HTML代码:

<template>
  <input v-model="name" ref="inputEl" />
  <input v-model="searchKeyword" ref="inputEl" />
</template>

TS 代码

<script setup lang="ts">
import { ref, watchEffect, watchPostEffect } from 'vue'
const name = ref('')
const searchKeyword = ref('')

// 防抖搜索,清理定时器
watchEffect((onCleanup) => {
  // 访问所有响应式依赖,确保watchEffect能追踪变化
  name.value
  searchKeyword.value
  // 实现防抖
  const t = setTimeout(() => {
    console.log("设置定时")
    doSearch() // 执行搜索
  }, 500)
  onCleanup(() => {
      console.log("清除定时")
      clearTimeout(timer) //清除定时
    })
})
</script>

第三方库 Lodash 防抖(项目常用)

VUE原生实现,开发很少用,一般直接使用成熟库,如:Lodash

功能强大,稳定,适合有多个输入框等复杂的场景

安装

npm i lodash

使用

import { debounce } from 'lodash';

// 延迟500ms执行
const fn = debounce(function(e) {
  console.log(e.target.value);
}, 500);

// 立即执行,leading=true,trailing=false
const btnFn = debounce(submit, 1000, { leading: true, trailing: false });

// 取消防抖(组件销毁时释放定时器,防止内存泄漏)
fn.cancel();

Lodash 参数说明:
_.debounce(func, wait, options)

  • wait:等待毫秒
  • options.leading:true=首次立即执行
  • options.trailing:true=延迟后执行最后一次
  • options.maxWait:最大等待时间(结合节流特性)

Vue3 + Lodash 实现防抖

<template>
  <input @input="handleInput" />
</template>
<script setup>
import { debounce } from './utils';

const query = (e) => {
  console.log("搜索", e.target.value);
};
// 生成防抖函数,仅创建一次
const handleInput = debounce(query, 400);
</script>

常见坑与优化

  1. 组件销毁未清除定时器 → 内存泄漏
    解决:lodash提供.cancel(),手写防抖可增加取消方法:

    function debounce(fn, delay) {
    let timer = null;
    const debounced = function (...args) {
     if (timer) clearTimeout(timer);
     timer = setTimeout(() => fn.apply(this, args), delay);
    };
    // 暴露取消方法
    debounced.cancel = () => clearTimeout(timer);
    return debounced;
    }
    // 组件卸载时调用 debounced.cancel()
    
  2. 每次渲染重复生成防抖函数,防抖失效
    Vue/React中必须缓存防抖函数(useCallback、setup顶层定义),不能写在渲染循环内部。

  3. delay 设置过小,失去防抖意义
    小于100ms基本和不防抖无区别,推荐300ms起步。


原文出处:/show_1GW3hqKEmf2H.html