一、防抖
防抖函数,可以这么理解,不是立即做,而是等待一段时间之后再做,如果等待期间又触发,那就重新计时。举个例子,就像游戏里的回城,如果被打断了,那就重新回城,又或者像电梯关门,如果在等待期间有人进电梯了,就会重新计算时间。 应用场景挺多的,比如搜索引擎里的搜索。输入关键词完毕后,等待一小段时间,才会发送http请求,而不是一输入内容就发送请求。
- 声明
debounce
函数
export const debounce = function (callback, delay) {
setTimeout(() => {
callback()
}, delay);
};
然而,这个只是将函数延迟了,并没有达到只执行一次的效果。所以可以这样做,声明一个timer
,每一次调用这个debounce
函数,就先把定时器清除了,这样就能保证定时器只执行一次.
var timer;
export const debounce = function (callback, delay) {
clearTimeout(timer);
timer = setTimeout(() => {
callback();
}, delay);
};
但是这样做,明显是污染了全局变量,所以可以考虑使用闭包
。
export const debounce = function (callback, delay) {
var timer;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
callback();
}, delay);
};
};
此时已经是能够实现效果了,可以实现只触发一次。
//高阶函数:函数内部返回一个新的函数
const debounce = utils.debounce(function () {
console.log("searchValue", searchValue.value);
}, 1000);
const onSearch = () => {
debounce();
};
还有完善一下传参。
//xx.vue
//高阶函数:函数内部返回一个新的函数
const debounce = utils.debounce(function (val) {
console.log('val',val);
}, 1000);
const onSearch = () => {
debounce(searchValue.value);
};
//debounce.js
export const debounce = function (callback, delay) {
var timer;
return function () {
clearTimeout(timer);
var args = arguments;
timer = setTimeout(()=> {
callback.apply(null, args);
}, delay);
};
};
二、节流
节流函数,可以这么理解,在一定时间内,只执行一次,现在写一下。
- 等待一段时间后才触发。 就像连续触发,开始一秒后执行一次,触发停止了,过了一秒执行最后一次。
//xxx.vue
const throttle = utils.throttle(function (val) {
console.log('val',val);
}, 1000);
const onSearch = () => {
throttle(searchValue.value);
};
//throttle.js
var timer;
return function () {
if (timer) return;
var args = arguments;
timer = setTimeout(() => {
callback.apply(null, args);
timer = null;
}, delay);
};
- 立即触发。 就像连续触发,刚开始触发时执行一次,触发停止了就不再执行。
export const throttle = function (callback, delay) {
var t;
return function () {
if (!t || Date.now() - t >= delay) {
//之前没有及时 或 距离上次执行的时间大于规定时间
callback.apply(null, arguments);
t = Date.now(); //得到当前时间搓
}
};
};
3.两者结合,默认立即触发
//throttle.js
export const throttle = function (callback, delay, immediately) {
if (immediately === undefined) {
immediately = true;
}
if (immediately) {
var t;
return function () {
if (!t || Date.now() - t >= delay) {
//之前没有及时 或 距离上次执行的时间大于规定时间
callback.apply(null, arguments);
t = Date.now(); //得到当前时间搓
}
};
} else {
var timer;
return function () {
if (timer) return;
var args = arguments;
timer = setTimeout(() => {
callback.apply(null, args);
timer = null;
}, delay);
};
}
};