函数节流(throttle)
-
指定时间间隔内只会执行一次任务
这里以判断页面是否滚动事件为例:
因为当在滚动的时候,浏览器会无时不刻地在计算判断是否滚动到底部的逻辑,而在实际的场景中是不需要这么做的,在实际场景中可能是这样的:在滚动过程中,每隔一段时间在去计算这个判断逻辑。而函数节流所做的工作就是每隔一段时间去执行一次原本需要无时不刻地在执行的函数,所以在滚动事件中引入函数的节流是一个非常好的实践:
//utils.js
//函数节流
export function throttle(fn, waitTime = 1000){
let lastTime = null
return function () {
let startTime = + new Date()
if (startTime - lastTime > waitTime || !lastTime) {
fn()
lastTime = startTime
}
}
}
let throttle = (fn, delay = 50) => {
// 节流 控制执行间隔时间 防止频繁触发 scroll resize mousemove
let stattime = 0;
return function (...args) {
let curTime = new Date();
if (curTime - stattime >= delay) {
fn.apply(this, args);
stattime = curTime;
}
}
}
使用方法
this.$refs.Throttle.addEventListener('scroll',
throttle(that.console, 300)
)
函数防抖(debounce)
-
任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。
这里用input框输入,搜索或者是核实用户名名称等功能为例:
很明显,这样的做法不好的是当用户输入第一个字符的时候,就开始请求判断了,不仅对服务器的压力增大了,对用户体验也未必比原来的好。而理想的做法应该是这样的,当用户输入第一个字符后的一段时间内如果还有字符输入的话,那就暂时不去请求判断用户名是否被占用。在这里引入函数防抖就能很好地解决这个问题
其实函数防抖的原理也非常地简单,通过闭包保存一个标记来保存 setTimeout 返回的值,每当用户输入的时候把前一个 setTimeout clear 掉,然后又创建一个新的 setTimeout,这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数了。
utils.js
//函数防抖
export function debounce(fn, interval = 300) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}
let debounce = (fn, time = 50) => { // 防抖动 控制空闲时间 用户输入频繁
let timer;
return function (...args) {
let that = this;
clearTimeout(timer);
timer = setTimeout(fn.bind(that, ...args), time);
}
}
使用方法
原生的js:
$('input.user-name').on('input', debounce( () => {
//somecode
}, 800)
在vue中的使用:
//Debounce.vue
<input type="text" @input='bindInputDebounce' >
methods:{
bindInputDebounce:debounce(function() {
console.log('bindInputDebounce')
})
}
总结
- 使用函数节流与函数防抖的目的,在开头的栗子中应该也能看得出来,就是为了节约计算机资源。
参考作者内容:函数节流与函数防抖