防抖和节流,这两种技术常用于优化高频触发的事件处理(如滚动、窗口大小调整、输入框搜索等):
1. 防抖函数(Debounce)
原理:在事件被触发后,延迟一段时间再执行回调函数。如果在延迟时间内再次触发事件,则重新计时。
/**
* 防抖函数
* @param {Function} func - 要执行的函数
* @param {number} delay - 延迟时间(毫秒)
* @param {boolean} immediate - 是否立即执行(可选,默认false)
* @returns {Function} - 防抖处理后的函数
*/
function debounce(func, delay, immediate = false) {
let timer = null;
return function(...args) {
// 如果已有定时器,清除它
if (timer) clearTimeout(timer);
// 是否需要立即执行
if (immediate && !timer) {
func.apply(this, args);
}
// 设置新的定时器
timer = setTimeout(() => {
timer = null;
if (!immediate) {
func.apply(this, args);
}
}, delay);
};
}
2. 节流函数(Throttle)
原理:在一定时间内,只执行一次回调函数。即使在这段时间内多次触发事件,也只会执行一次。
/**
* 节流函数(时间戳版)
* @param {Function} func - 要执行的函数
* @param {number} limit - 限制时间(毫秒)
* @returns {Function} - 节流处理后的函数
*/
function throttle(func, limit) {
let lastExecTime = 0;
return function(...args) {
const now = Date.now();
// 如果距离上次执行超过了限制时间
if (now - lastExecTime >= limit) {
func.apply(this, args);
lastExecTime = now;
}
};
}
3. 使用示例
// 假设有一个搜索框输入事件
const searchInput = document.getElementById('search-input');
// 使用防抖处理搜索输入
searchInput.addEventListener('input', debounce((e) => {
console.log('搜索:', e.target.value);
// 执行搜索逻辑...
}, 300));
// 使用节流处理滚动事件
window.addEventListener('scroll', throttle(() => {
console.log('滚动事件被触发(节流)');
// 执行滚动相关逻辑...
}, 200));
4. 区别总结
- 防抖:适用于需要避免频繁触发的场景(如搜索框输入联想、按钮点击防止重复提交)。
- 节流:适用于需要限制执行频率的场景(如滚动加载、窗口大小调整)。
5.vue中实现
// utils/tools.js
export function debounce(func, delay = 300) {
let timer = null
return function(...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, delay)
}
}
export function throttle(func, limit = 500) {
let lastExecTime = 0
return function(...args) {
const now = Date.now()
if (now - lastExecTime >= limit) {
func.apply(this, args)
lastExecTime = now
}
}
}
组件中使用
<template>
<view>
<button @click="debouncedHandle">防抖处理</button>
</view>
</template>
<script>
import { debounce } from '@/utils/tools'
export default {
data() {
return {
inputValue: ''
}
},
created() {
this.debouncedHandle = debounce(this.handleInput, 300)
},
methods: {
handleInput() {
console.log('处理输入:', this.inputValue)
}
}
}
</script>