1.防抖和节流的区别
防抖:在n秒内,多次触发,只执行最后一次
节流:事件多次触发,每间隔n秒执行一次
无论是防抖还是节流本质上事件在触发的时候都是触发内层的匿名函数,之所以能够实现防抖和节流,是因为我们在外层的函数里面声明了timer这样的一个变量,然后在内层通过对timer也就是定时器的一个判断,最终来实现。从代码的角度,它是应用到了闭包的原理,所以说后面如果说问到闭包的实际应用场景,那防抖和节流就算一种。
防抖和节流本质上是对闭包和匿名函数的应用。通过定义一个定时器变量timer,然后在匿名函数中对timer进行设置和清除。防抖和节流的主要区别就是定时器的设置和清除时机不同。
定时器方式实现防抖和节流时区别:(清除定时器时机不同)
- 防抖是判断如果定时器存在,则清除当前定时器并重新设置定时器,否则执行func函数并改变其this指向和传参;
- 节流是如果定时器不存在时,则设置定时器,并且在定时器内部调用func函数并改变this指向和传参,同时timer=null保证定时器只触发一次
- 如果有立即执行函数,两者判断方法一致
注意如果函数有参数,是在返回函数中获取上下文this和参数,并通过fn.apply(context,args) 方式进行传递
2.防抖:
<input type="text" class="inputDiv" />
<script>
// 防抖:间隔n秒内重复触发,只执行最后一次
// 防抖定时器:n秒内,如果定时器存在则清除定时器,并重新设置定时器
// 注意this和args必须再返回的函数中接收
function debounce(func, wait = 1000, immediate = false) {
var timer = null;
return function () {
// 用于传参
var context = this;
var args = arguments;
if(immediate){
func.apply(context, args);
// 立即执行后必须将immediate设置为fasle
immediate = false;
return;
}
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
var inputDiv = document.getElementsByClassName("inputDiv")[0];
// inputDiv.addEventListener("input", function (e) {
// console.log(e.target.value);
// });
var submit = function (e) {
console.log(e.target.value);
}
var debounceFn = debounce(submit, 1000, immediate = false)
inputDiv.addEventListener("input", this.debounceFn);
</script>
3.节流:
<div class="box" style="width: 100px;height: 100px; background-color: aqua;"></div>
<script>
// 节流:无论触发多少次,都是间隔n秒执行一次
// 节流:如果定时器不存在则设置定时器,并在定时器函数内部清空timer
function throttle(func, wait = 1000, immediate = false){
let timer = null;
return function(){
let context = this;
let args = arguments;
if(immediate){
func.apply(context, args);
// 立即执行后必须将immediate设置为fasle
immediate = false;
return;
}
if(!timer){
timer = setTimeout(function(){
// 注意函数调用位置和定时器清空时机
func.apply(context, args)
timer = null;
},wait);
}
}
}
let boxDiv = document.getElementsByTagName("div")[0];
console.log(boxDiv);
let move = function(e){
console.log("移动了",e);
}
let throttleFn = throttle(move,1000, true);
boxDiv.addEventListener("mousemove", throttleFn);
</script>
4.vue项目中使用防抖和节流函数
先在data中调用debounce函数并返回,再直接进行调用
data() {
const onDebounce = this.debounce(this.onSubmit, 500, true)
return {
onDebounce
};
},
methods: {
onSubmit() {
console.log("submit!");
},
debounce(func, wait = 500, immediate) {
let timer;
return function () {
let context = this;
let arg = arguments;
if (immediate) {
func.apply(context, arg);
immediate = false;
return;
}
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, arg);
}, wait);
};
},
},
<el-button type="primary" @click="onDebounce">立即创建</el-button>