防抖函数与节流函数

应用场景浏览器

实际工做中,咱们常常性的会经过监听某些事件完成对应的需求,好比:app

  1. 经过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮
  2. 经过监听 resize 事件,对某些自适应页面调整DOM的渲染(经过CSS实现的自适应再也不此范围内)
  3. 经过监听 keyup 事件,监听文字输入并调用接口进行模糊匹配
  4. ...

常规实现,以监听 scroll 事件为例函数

  咱们先来看一下scroll事件的触发频率oop

  

window.onscroll  = function () {
    //滚动条位置
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);
}

效果以下:性能

从效果上,咱们能够看到,在页面滚动的时候,会在短期内触发屡次绑定事件。优化

咱们知道DOM操做是很耗费性能的,若是在监听中,作了一些DOM操做,那无疑会给浏览器形成大量性能损失。this

下面咱们进入主题,一块儿来探究,如何对此进行优化。spa

 

函数防抖3d

定义:屡次触发事件后,事件处理函数只执行一次,而且是在触发操做结束时执行。code

原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。

var timer;
    window.onscroll = function (e) {
        //防抖,当给timer赋值后,滚动又清空,直到中止滚动,执行timer函数
        if(timer){
          clearTimeout(timer)
        }  
        timer = setTimeout(function(){
          //执行事件函数  addLiScroll();
       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)

 

函数节流

定义:触发函数事件后,短期间隔内没法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。

原理:对处理函数进行延时操做,若设定的延时到来以前,再次触发事件,则清除上一次的延时操做定时器,从新定时。

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);
    }
}

 

防抖函数的封装使用

/**
 * 节流函数
 * @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)

  封装简便的写法

  

var time;
    window.onscroll = function (e) { //节流, 每隔多久执行一次
        if(!time){
          time = setTimeout(() => {
            //执行的事件             addLiScroll();
            time = undefined;
          }, 1000);
        }
        
    }
相关文章
相关标签/搜索