防抖和节流

防抖和节流

防抖(Debounce)和节流(Throttle)都是控制函数执行频率的技术,但它们的目的和行为有所不同:

防抖(Debounce)

防抖技术确保函数在事件被触发一定时间后再执行,如果在这个时间间隔内又被重新触发,则重新计时。防抖常用于搜索框输入、窗口大小调整等操作,确保只有在用户停止输入或调整后才执行函数。

  • 行为:函数只有在最后一次触发事件后的等待时间结束后才执行一次。
  • 用途:适用于那些希望在一系列连续操作结束后才执行一次的场景。
  • 效果:可以减少函数的执行次数,特别是在事件触发非常频繁时。

节流(Throttle)

节流技术确保函数在指定的时间间隔内最多只执行一次,不管事件触发了多少次。节流常用于滚动事件、窗口大小调整等操作,确保函数不会过于频繁地执行。

  • 行为:函数在指定的时间间隔内只执行一次,不管事件触发了多少次。
  • 用途:适用于那些需要在一段时间内只响应一次的场景,比如滚动事件处理。
  • 效果:可以限制函数的执行频率,使得函数执行更加平滑和可控。

区别

  • 触发时机:防抖是事件触发后等待一定时间才执行,而节流是保证在固定时间间隔内只执行一次。
  • 适用场景:防抖适用于用户操作结束后才需要执行的场景,节流适用于需要在连续操作中平滑执行的场景。
  • 执行次数:防抖可能在连续触发事件时一次也不执行,节流则至少会执行一次。
  • 实现方式:防抖通常使用定时器(setTimeout)实现,节流可以使用定时器或时间戳(requestAnimationFrame 或 Date.now())实现。

示例代码

防抖

1
2
3
4
5
6
7
8
9
10
11
function debounce(func, wait) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}

节流

1
2
3
4
5
6
7
8
9
10
11
12
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}

在实际应用中,选择防抖还是节流取决于具体的需求和场景。

防抖和节流在实际应用中

当然可以,以下是防抖(Debounce)和节流(Throttle)在实际应用中的一些例子:

防抖(Debounce)的例子:搜索框输入

场景:在搜索引擎或应用的搜索框中输入文字时,通常不希望用户每输入一个字符就发送一次请求,因为这会极大地增加服务器的负担。
实现:使用防抖技术,只有当用户停止输入一定时间后,才发送请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 假设有一个搜索函数 search
function search(query) {
console.log('Searching for:', query);
// 发送请求到服务器...
}
// 防抖函数
function debounce(func, wait) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
// 创建防抖后的搜索函数
const debouncedSearch = debounce(search, 300); // 300ms 防抖时间
// 绑定到输入框的事件
const searchInput = document.getElementById('search-input');
searchInput.addEventListener('input', (event) => {
debouncedSearch(event.target.value);
});

节流(Throttle)的例子:滚动事件处理

场景:在页面滚动时,可能需要执行一些操作,如无限滚动加载、调整布局等。如果每次滚动都执行这些操作,会导致性能问题。
实现:使用节流技术,确保在用户滚动过程中,无论滚动多快,指定时间内只执行一次函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 假设有一个处理滚动的函数 handleScroll
function handleScroll() {
console.log('Handling scroll event...');
// 执行滚动相关的操作...
}
// 节流函数
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
};
}
// 创建节流后的滚动处理函数
const throttledScroll = throttle(handleScroll, 100); // 100ms 节流时间
// 绑定到滚动事件
window.addEventListener('scroll', throttledScroll);

在这两个例子中,防抖用于减少频繁的输入事件处理,而节流用于控制滚动事件的处理频率。这两种技术都有助于提高应用的性能和用户体验。

防抖(Debounce)是一种限制函数执行频率的技术,通常用于处理频繁触发的事件,如窗口大小调整、滚动、键盘输入等。防抖的基本思想是:在指定时间内多次触发同一事件时,只执行最后一次事件的处理函数。
在 Vue 中实现防抖功能,可以通过以下几种方式:

1. 使用原生 JavaScript 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function debounce(func, delay) {
let timer;
return function(...args) {
const context = this;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args);
}, delay);
};
}
export default {
data() {
return {
// ...
};
},
methods: {
handleScroll() {
console.log('滚动事件触发');
},
debounceScroll() {
return debounce(this.handleScroll, 500);
}
},
mounted() {
window.addEventListener('scroll', this.debounceScroll());
},
beforeDestroy() {
window.removeEventListener('scroll', this.debounceScroll());
}
};

2. 使用第三方库(如 lodash)

1
npm install lodash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import _ from 'lodash';
export default {
data() {
return {
// ...
};
},
methods: {
handleScroll() {
console.log('滚动事件触发');
}
},
mounted() {
window.addEventListener('scroll', _.debounce(this.handleScroll, 500));
},
beforeDestroy() {
window.removeEventListener('scroll', _.debounce(this.handleScroll, 500));
}
};

3. 使用 Vue 的 Composition API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { debounce } from 'lodash';
export default {
setup() {
const handleScroll = () => {
console.log('滚动事件触发');
};
const debouncedHandleScroll = debounce(handleScroll, 500);
onMounted(() => {
window.addEventListener('scroll', debouncedHandleScroll);
});
onBeforeUnmount(() => {
window.removeEventListener('scroll', debouncedHandleScroll);
});
return {};
}
};

注意事项

  • 防抖与节流的区别:防抖是等待一段时间后只执行最后一次事件的处理函数,而节流是每隔一段时间执行一次事件的处理函数。
  • 清除定时器:在组件销毁时,记得清除定时器,避免内存泄漏。
  • 参数传递:在使用防抖函数时,确保正确传递事件的参数,如 event 对象等。