小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
项目中遇到用户点击按钮会发送多次请求,会白白占用不必要的资源,
<template>
<div class="home">
<button @click="onCLick">快点我</button>
</div>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
@Component({
components: {},
})
export default class Home extends Vue {
onCLick() {
console.log("我被点了,被点了。。。")
}
}
</script>
思来想去发现可以用函数防抖来解决该问题。
函数防抖 (debounce)
- 函数防抖: 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时,先计算时间后执行。 说白了就是为了减少频繁发生的事件的资源请求,如果在等待时间内用户没有操作,则执行回调,如果有操作,继续等待相应时间间隔。
所以在闭包函数内,初始化一个时间参数timer,如果timer为空,则表示回调事件没执行或者已执行完毕,代表在等待时间内用户没有操作,相反,如果timer不为null,清空timer,重新计时。
<template>
<div class="home">
<button @click="onCLick">函数防抖</button>
</div>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
@Component({
components: {},
})
export default class Home extends Vue {
// eslint-disable-next-line @typescript-eslint/ban-types
debounce(func: Function, time: number, immediate = false) {
let timer: number | null = null;
return (...args: any) => {
if (timer) clearInterval(timer)
if (immediate) {
if (!timer) func.apply(this, args);
timer = window.setTimeout(() => {
timer = null
}, time)
} else {
timer = window.setTimeout(() => {
func.apply(this, args)
}, time)
}
}
}
// onCLick = this.debounce(() => {
// console.log("我被点了,被点了。。。")
// }, 500)
onCLick = this.debounce(() => {
console.log("我被点了,被点了。。。")
}, 500,true)
}
</script>
函数节流 (throttle)
- 函数节流: n秒内回调函数只会被执行一次,先执行后计算。 函数节流的目的是为了让函数在特定时间内执行一次,用setTimeout实现,执行完回调将timer置空。
<template>
<div class="home">
<button @click="onCLick">函数节流</button>
</div>
</template>
<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
@Component({
components: {},
})
export default class Home extends Vue {
// eslint-disable-next-line @typescript-eslint/ban-types
throttle(func: Function, time: number, immediate = false) {
if (immediate) {
let prevTime = 0;
return (...args: any) => {
let nowTime = Date.now();
if (nowTime - prevTime >= time) {
func.apply(this, args)
prevTime = nowTime
}
}
} else {
let timer: number | null = null;
return (...args: any) => {
if (!timer) {
func.apply(this, args)
timer = window.setTimeout(() => {
if (timer) clearInterval(timer)
timer = null
}, time);
}
}
}
}
onCLick = this.throttle(() => {
console.log("我被点了,被点了。。。")
}, 500)
// onCLick = this.throttle(() => {
// console.log("我被点了,被点了。。。")
// }, 500, true)
}
</script>