怎么使用debounce(防抖)处理实时搜索
防抖(Debounce)是一种常用的性能优化技术,特别适用于像实时搜索这类频繁触发事件的场景。它的核心思想是在事件被触发后,延迟一定时间再执行回调函数,如果在延迟时间内该事件又被触发了,就重新计时,直到延迟时间内没有新的事件触发,才执行回调函数。下面以原生 JavaScript 和 Vue.js 为例,介绍如何使用防抖处理实时搜索:
原生 JavaScript 中使用防抖处理实时搜索
html
预览
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Debounce Search</title>
</head>
<body>
<input type="text" id="searchInput" placeholder="输入关键词进行搜索">
<script>
// 模拟数据数组
const data = [
{ id: 1, cnname: "张三", enname: "Zhang San" },
{ id: 2, cnname: "李四", enname: "Li Si" },
{ id: 3, cnname: "王小明", enname: "Wang Xiaoming" },
{ id: 4, cnname: "阿里巴巴", enname: "Alibaba" },
{ id: 5, cnname: "腾讯科技", enname: "Tencent" }
];
// 防抖函数实现
function debounce(func, delay) {
let timer;
return function () {
const context = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
// 模糊搜索函数
function fuzzySearch(array, keyword) {
if (!keyword) return array;
const lowerKeyword = keyword.toLowerCase();
return array.filter(item => {
return (item.cnname && item.cnname.toLowerCase().includes(lowerKeyword)) ||
(item.enname && item.enname.toLowerCase().includes(lowerKeyword));
});
}
// 获取搜索输入框元素
const searchInput = document.getElementById('searchInput');
// 使用防抖函数包装搜索函数
const debouncedSearch = debounce(() => {
const keyword = searchInput.value;
const result = fuzzySearch(data, keyword);
console.log("搜索结果:", result);
}, 300); // 延迟300毫秒执行搜索
// 监听输入框的input事件
searchInput.addEventListener('input', debouncedSearch);
</script>
</body>
</html>
在上述代码中:
debounce
函数接收要延迟执行的函数func
和延迟时间delay
作为参数,返回一个新的函数。这个新函数在每次被调用时,会清除之前设置的定时器(如果存在),并重新设置一个新的定时器,在延迟时间到达后执行func
。fuzzySearch
是模糊搜索函数,用于根据关键词对数据数组进行过滤。- 通过
addEventListener
监听输入框的input
事件,并将debouncedSearch
函数作为回调,这样在用户快速输入时,搜索函数不会频繁执行,而是在用户停止输入 300 毫秒后才执行。
在 Vue.js 中使用防抖处理实时搜索
vue
<template>
<div>
<h3>使用防抖的实时搜索</h3>
<input
type="text"
v-model="keyword"
placeholder="输入中文或英文关键词..."
class="search-input"
>
<div class="result-list">
<div v-for="item in filteredData" :key="item.id" class="result-item">
<span>ID: {{ item.id }}</span>
<span>中文名称: {{ item.cnname }}</span>
<span>英文名称: {{ item.enname }}</span>
</div>
</div>
</div>
</template>
<script>
// 防抖函数
export function debounce(func, delay) {
let timer;
return function () {
const context = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
export default {
data() {
return {
keyword: '',
originalData: [
{ id: 1, cnname: "张三", enname: "Zhang San" },
// ... 同上数据 ...
],
filteredData: []
};
},
mounted() {
// 使用防抖函数包装搜索方法
this.debouncedSearch = debounce(this.searchData, 300);
// 监听keyword变化,触发防抖后的搜索
this.$watch('keyword', this.debouncedSearch);
},
methods: {
searchData() {
if (!this.keyword) {
this.filteredData = this.originalData;
return;
}
const lowerKeyword = this.keyword.toLowerCase();
this.filteredData = this.originalData.filter(item => {
return (item.cnname && item.cnname.toLowerCase().includes(lowerKeyword)) ||
(item.enname && item.enname.toLowerCase().includes(lowerKeyword));
});
}
}
};
</script>
<style>
.search-input {
padding: 8px;
width: 300px;
border: 1px solid #ddd;
border-radius: 4px;
}
.result-list {
margin-top: 15px;
}
.result-item {
padding: 8px;
border-bottom: 1px solid #f0f0f0;
}
</style>
在 Vue 项目中:
-
定义了
debounce
函数,原理和原生 JavaScript 中的防抖函数一致。 -
在
mounted
生命周期钩子中,使用防抖函数包装searchData
方法,并通过$watch
监听keyword
的变化,触发防抖后的搜索操作。这样在用户输入过程中,搜索方法不会频繁执行,从而提升性能。
通过以上两种方式,都能有效利用防抖技术来优化实时搜索功能,减少不必要的函数调用,提升应用的性能和用户体验。
Lodash 中的防抖怎么使用
Lodash 提供了强大的 debounce
函数,相比手动实现更加健壮且功能丰富(如支持立即执行、取消、flush 等)。以下是它的详细用法:
1. 基础用法:延迟执行搜索
javascript
import { debounce } from 'lodash';
// 模拟搜索函数(实际项目中可能是API请求)
function search(keyword) {
console.log('执行搜索:', keyword);
// 返回搜索结果...
}
// 创建防抖版本的搜索函数,延迟300ms
const debouncedSearch = debounce(search, 300);
// 绑定到输入事件
document.getElementById('searchInput').addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
- 效果:用户输入时,只有停止输入 300ms 后 才会执行
search
函数。
2. 常用配置选项
2.1 leading
:是否立即执行
javascript
// 立即执行首次调用,之后的调用需等待300ms冷却期
const debouncedSearch = debounce(search, 300, {
leading: true, // 首次立即执行
trailing: true // 最后一次也执行(默认值)
});
- 场景:适合需要立即反馈的场景(如搜索建议),同时避免连续触发。
2.2 maxWait
:最长等待时间
javascript
// 最长等待500ms,即使持续输入也会每500ms执行一次
const debouncedSearch = debounce(search, 300, {
maxWait: 500
});
- 场景:适合需要定期更新结果的场景(如自动保存)。
3. 取消与立即执行
3.1 cancel()
:取消待执行的函数
javascript
// 取消未执行的搜索(如用户离开页面时)
debouncedSearch.cancel();
3.2 flush()
:立即执行待执行的函数
javascript
// 立即执行并获取结果(如用户点击搜索按钮时)
debouncedSearch.flush();
4. 在 Vue.js 中的完整示例
vue
<template>
<div>
<input
v-model="keyword"
@input="handleInput"
placeholder="输入关键词..."
>
<button @click="flushSearch">立即搜索</button>
</div>
</template>
<script>
import { debounce } from 'lodash';
export default {
data() {
return {
keyword: '',
debouncedSearch: null
};
},
created() {
// 创建防抖函数
this.debouncedSearch = debounce(this.fetchResults, 300);
},
methods: {
// 实际执行搜索的方法
fetchResults() {
console.log('API请求:', this.keyword);
// 调用API获取搜索结果...
},
// 处理输入事件
handleInput() {
this.debouncedSearch();
},
// 立即执行搜索
flushSearch() {
this.debouncedSearch.flush();
}
},
beforeDestroy() {
// 组件销毁前取消未执行的请求
this.debouncedSearch.cancel();
}
};
</script>
5. 与原生防抖的区别
特性 | 原生实现 | Lodash debounce |
---|---|---|
立即执行(leading) | 需手动实现 | ✅ 内置支持 |
最长等待时间(maxWait) | 不支持 | ✅ 防止长时间不执行 |
取消 / 立即执行 | 需手动管理定时器 | ✅ cancel()/flush() |
函数参数传递 | 需要手动处理上下文 | ✅ 自动保留参数 |
注意事项
-
安装依赖:
bash
npm install lodash
-
按需导入:
javascript
// 推荐:只导入debounce函数,减少打包体积 import debounce from 'lodash/debounce';
-
性能考量:
- 防抖延迟时间不宜过短(如 <50ms),否则可能失去优化意义。
- 对于高频触发的场景(如滚动、窗口调整),建议使用 节流(throttle) 。
通过 Lodash 的 debounce
,你可以更优雅地处理实时搜索、自动保存等高频触发场景,同时避免手动管理定时器的复杂性。