• 防抖函数与节流函数


    应用场景

    实际工作中,我们经常性的会通过监听某些事件完成对应的需求,比如:

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

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

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

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

      效果如下:

    从效果上,我们可以看到,在页面滚动的时候,会在短时间内触发多次绑定事件。

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

    下面我们进入主题,一起来探究,如何对此进行优化。

    函数防抖

    定义:多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行。

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

      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)
    复制代码

    文中如果出现错误,希望小伙伴们可以谅解,更希望可以给予指正

  • 相关阅读:
    洛谷P2389 电脑班的裁员(区间DP)
    停更祭
    搜索 水题&&错误集锦
    模板——最小生成树prim算法&&向前星理解
    单源最短路dijkstra算法&&优化史
    模板——最小生成树kruskal算法+并查集数据结构
    卡常三连(快读快写+re)
    模板——STL队列
    起点
    《2016年十一月十三日周总结》
  • 原文地址:https://www.cnblogs.com/sugar-tomato/p/10484357.html
Copyright © 2020-2023  润新知