防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
/**
* @des 防抖 ,多次只执行最后一次
* @param func 需要包装的函数
* @param delay 延迟时间,单位ms
* @param immediate 是否默认执行一次(第一次不延迟)
*/
class Debounced {
public use = (
func: Function,
delay: number,
immediate: boolean = false
): Function => {
let timer: NodeJS.Timeout;
return (...args: any) => {
if (immediate) {
func.apply(this, args);
immediate = false;
return;
}
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
};
}
/**
* @des 节流,多次都会执行,只是间隔一段时间再执行
* @param func 需要包装的函数
* @param delay 延迟时间,单位ms
* @param immediate 是否默认执行一次(第一次不延迟)
*/
class Throttle {
private timer: NodeJS.Timeout | undefined;
private stop: boolean = false;
private death: boolean = false;
public use(
func: Function,
delay: number,
immediate: boolean = false
): Function {
let flag = true;
const self = this;
return (...args: any) => {
if (this.death) {
func.apply(this, args);
return;
}
if (this.stop) {
func.apply(this, args);
return;
}
if (immediate) {
func.apply(this, args);
immediate = false;
return;
}
if (!flag) {
return;
}
flag = false;
self.timer = setTimeout(() => {
func.apply(this, args);
flag = true;
}, delay);
};
}
// 销毁
public destroy() {
this.death = true;
this.stop = true;
if (this.timer) {
clearTimeout(this.timer);
this.timer = undefined;
}
}
// 开启
public open() {
if (!this.death) {
this.stop = false;
}
}
// 关闭
public close() {
this.stop = true;
}
}
使用
<template>
<div id="debounced-test">
<v-button @click="handelClickByDebounced">防抖</v-button>
<v-button @click="handelClickByThrottle" type="success">节流</v-button>
<v-button @click="changeStopThrottle(throttle.stop)" type="warning">
{{ throttle.stop ? '开启' : '关闭' }}节流
</v-button>
<v-button @click="destroyThrottle" type="danger">销毁节流函数</v-button>
</div>
</template>
<script lang="ts">
import { Debounced, Throttle } from '@/utils'
import { Vue, Component } from 'vue-property-decorator'
@Component
export default class DebouncedTest extends Vue {
private count: number = 1
private debouncedUse: Function = new Debounced().use(this.request, 1000)
private throttle = new Throttle()
private throttleUse: Function = this.throttle.use(this.request, 1000)
private request(params: any) {
console.log('this的指向', this);
console.log('参数', params);
console.log(this.count++)
}
// 防抖调用
private handelClickByDebounced() {
this.debouncedUse(123)
}
// 节流调用
private handelClickByThrottle() {
this.throttleUse('截流函数')
}
// 停止 | 开启节流函数
private changeStopThrottle(action: boolean) {
action ? this.throttle.open() : this.throttle.close()
}
// 销毁节流函数
private destroyThrottle() {
this.throttle.destroy()
}
}
</script>