防抖(Debounce)和节流(Throttle)
都是用来控制某个函数在一定时间内触发次数,两者都是为了减少触发频率,以便提高性能以及避免资源浪费。
防抖函数:
指的是触发事件以后,在n秒内只会执行一次,如果在此期间又触发了事件,则会重新计时。
举个栗子:就好比有人进电梯(触发事件),这个时候电梯会在5秒后触发。如果在此期间又进来了一个人,那么这时候又会重新计时,5秒后出发。最终只有最后一次触发的事件生效。
// 防抖 事件触发 n 秒后执行一次, 如果在 n 秒内重复触发则重新计算函数执行时间
function debounce(func, delay) {
// 设置标识符
let timer = null;
return function () {
// 判断定时器是否存在,清除定时器
timer && clearTimeout(timer)
// 重新调用setTimeout
timer = setTimeout(() => {
func.apply(this, arguments)
timer = null;
}, delay)
}
}
函数节流:
规定一个单位时间,在这个单位时间内,无论触发多少次事件,只会执行一次函数。
// 时间戳方式
// 节流 事件连续触发在n秒内只触发一次
function throttle(func, delay) {
// last为上一次触发回调的时间
let last = 0;
// 将throttle处理结果当作函数返回
return function() {
// 保留调用时的this上下文
let context = this;
// 保留调用时传入的参数
let args = arguments;
// 记录本次触发回调的时间
let now = Date.now();
// 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
if (now - last >= delay) {
// 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
last = now
func.apply(this, args);
}
}
}
// 定时器方式:定时器实现的节流函数在第一次触发时不会执行,而是在 delay 秒之后才执行,当最后一次停止触发后,还会再执行一次函数
function throttle1(func, delay) {
let sign = true;
return function() {
// 在函数开头判断标志是否为 true,不为 true 则中断函数
if (!sign) return;
// sign 设置为 false,防止执行之前再被执行
sign = false;
setTimeout(() => {
func.apply(this, arguments)
// 执行完事件之后,重新将这个标志设置为 true
sign = true;
}, delay)
}
}
- 在vue项目中往往通过引入lodash库
安装lodash库:
// Yarn
yarn add lodash
// NPM
npm install lodash --save
引入防抖和节流函数并使用:
<template>
<button @click="throttledMethod()">Click me as fast as you can!</button>
</template>
<script>
import { throttle, debounce } from 'lodash'
export default {
methods: {
// 节流
throttledMethod: throttle(function() {
console.log('Hello Wangjiajia!')
}, 2000)
// 防抖
throttledMethod: debounce(function() {
console.log('Hello Jiajiawang!')
}, 2000)
}
}
</script>