应用场景浏览器
实际工做中,咱们常常性的会经过监听某些事件完成对应的需求,好比:app
常规实现,以监听 scroll 事件为例函数
咱们先来看一下scroll事件的触发频率oop
window.onscroll = function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
效果以下:性能
从效果上,咱们能够看到,在页面滚动的时候,会在短期内触发屡次绑定事件。优化
咱们知道DOM操做是很耗费性能的,若是在监听中,作了一些DOM操做,那无疑会给浏览器形成大量性能损失。this
下面咱们进入主题,一块儿来探究,如何对此进行优化。spa
函数防抖code
定义:屡次触发事件后,事件处理函数只执行一次,而且是在触发操做结束时执行。blog
原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。
scroll 的一个简单例子
let timer;
window.onscroll = function () {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
timer = undefined;
},200)
}
效果以下:滚动结束触发事件
防抖函数的封装使用
/**
* 防抖函数
* @param method 事件触发的操做
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(method,delay) {
let timer = null;
return function () {
let self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
函数防抖的适用性:
经过上面的例子,咱们知道咱们能够经过函数防抖,解决了屡次触发事件时的性能问题。
好比,咱们在监听滚动条位置,控制是否显示返回顶部按钮时,就能够将防抖函数应用其中。
但依然有些功能并不适用:
当咱们作图片懒加载(lazyload)时,须要经过滚动位置,实时显示图片时,若是使用防抖函数,懒加载(lazyload)函数将会不断被延时,
只有停下来的时候才会被执行,对于这种须要实时触发事件的状况,就显得不是很友好了。
下面开始介绍函数节流,经过设定时间片,控制事件函数间断性的触发。
函数节流
定义:触发函数事件后,短期间隔内没法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。
原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。
scroll 的一个简单例子
let startTime = Date.now(); //开始时间
let time = 500; //间隔时间
let timer;
window.onscroll = function throttle(){
let currentTime = Date.now();
if(currentTime - startTime >= time){
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
startTime = currentTime;
}else{
clearTimeout(timer);
timer = setTimeout(function () {
throttle()
}, 50);
}
}
效果以下:每隔500毫秒触发一次事件
防抖函数的封装使用
/**
* 节流函数
* @param method 事件触发的操做
* @param mustRunDelay 间隔多少毫秒须要触发一次事件
*/
function throttle(method, mustRunDelay) {
let timer,
args = arguments,
start;
return function loop() {
let self = this;
let now = Date.now();
if(!start){
start = now;
}
if(timer){
clearTimeout(timer);
}
if(now - start >= mustRunDelay){
method.apply(self, args);
start = now;
}else {
timer = setTimeout(function () {
loop.apply(self, args);
}, 50);
}
}
}
window.onscroll = throttle(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},800)
文中若是出现错误,但愿小伙伴们能够谅解,更但愿能够给予指正