zoukankan      html  css  js  c++  java
  • 防抖函数与节流函数

    应用场景

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

    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操作,那无疑会给浏览器造成大量性能损失。

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

    函数防抖

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

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

    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);
            }
            
        }
  • 相关阅读:
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.2)- 在串行NOR Flash XIP调试原理
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(2.1)- 玩转板载OpenSDA,Freelink调试器
    痞子衡嵌入式:史上最强i.MX RT学习资源汇总(持续更新中...)
    痞子衡嵌入式:终于可以放开聊一聊i.MXRT1170这颗划时代MCU了
    痞子衡嵌入式:MCUBootUtility v2.0来袭,i.MXRT1010哪里跑
    痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU硬件那些事(1)- 官方EVK简介
    3万字总结,Mysql优化之精髓
    不停机替换线上代码? 你没听错,Arthas它能做到
    Springboot 2.x 如何解决重复提交 (本地锁的实践)
    MYSQL插入千万数据的工具类
  • 原文地址:https://www.cnblogs.com/Tohold/p/10449933.html
Copyright © 2011-2022 走看看