目的
其实对于刚刚接触防抖节流的人来说,这两者好像常常一起说,而不是单拎出来说,实际上,他们是有区别的,针对的特定场景也不同,希望我的浅薄认知可以帮助到你
相同点:其实都是用于处理函数触发频次过高的问题
不同点:
1.防抖是说在规定时间内如果再度触发了这个事件,那么之前的待执行事件将会终止,转而重新计时,大白话就是---规定时间内只执行一次,如果再度触发就终止并且重新计时
2.节流是说,当事件执行后,规定时间内如果再度触发此事件,将不会执行(不生效),大白话说就是---函数执行后,在将来的一段时间内无法执行。
场景:节流---搜索联想功能
防抖---手机号等需要判断的输入框(用户输入完后再判断)
难点:防抖节流它涉及到闭包和this指向的问题,我个人认为实现一个简单的防抖节流搞懂闭包就行了,所以这里只是实现一个简单的功能。
闭包:就是函数嵌套函数,内部函数使用了外部函数的变量,此时我们的js垃圾回收机制,它无法判断这个变量是不是应该被回收,导致这个变量一直在内存中,大家好好想想,那这个变量是不是就永远留着了呢,是不是就可以用来当作判断条件了呢?
代码部分
html:防抖和节流的html部分我写在一起了
<template>
<input type="text" placeholder="测试防抖" v-model="inputVal" @keydown="search">
<input type="text" placeholder="测试节流" v-model="inputVal2" @keydown="searchTwo">
</template>
<script setup>
import { ref } from 'vue';
import { debounce } from '@utils/debounce.js'
import { throttle } from '@utils/throttle.js'
let inputVal = ref('')
let inputVal2 = ref('')
//input 防抖
const search = debounce(function(){
console.log('发送了请求,防抖');
},1000)
//input 节流
const searchTwo = throttle(function(){
console.log('发送了请求,节流');
},1000,{
leading:false,
trailing:true
})
</script>
<style scoped>
</style>
防抖实现:
大家仔细看,这个debounce函数是不是函数嵌套函数,并且内部函数使用了外部函数的timer这个变量,所以这里构成了闭包!!!,这个timer就可以当作后续的判断条件了
我知道,肯定会有人想,为啥let timer = null这句话只初始化一次呢其实我们在防抖函数中是return了一个函数,意味着此时在html中search触发的只是return后的东西,整个函数debounce其实就执行了一次。
//这是封装的一个防抖函数
//防抖,理解为游戏中的回程,即在为施法时间内,再度触发,会取消之前的施法,再重新读条
//细节 let timer = null 这句实际上在只会初始化一次,这里的作用则是驻留变量
export function debounce (fun,time = 1000) {
let timer = null
return function () {
//如果之前的定时器存在,那就清除它
if(timer){
clearInterval(timer)
}
timer = setTimeout(()=>{
fun();
}, time);
}
}
节流的实现:
当把防抖理解了那节流就水到渠成了,所以这里我就不解释了,总体也还是构成闭包。
//节流,理解为游戏中的技能cd,执行一次后,需要等冷却时间到了后,才能触发
export function throttle(fun,time=1000) {
let interval = false;//当前函数的状态(冷却或未冷却)
return function () {
if(interval) {
console.log('冷却中,无法执行');
return;
}else {//未冷却,可以执行
interval = true;
fun()
setTimeout(()=>{
interval = false;
},time)
}
}
}
结语:如果我的代码或者语句有什么问题请告知我,如果能给我说明一下就更好了。