• js节流防抖函数


    一、防抖函数

    当我们的回调函数(尤其是异步操作,比如请求数据)在短时间内,被连续调用时,会出现卡顿现象,此时的用户体验下降和性能消耗增大;

    所以需要添加防抖函数来解决:在设定的事件间隔,n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时,只执行最后一次操作;这样可以减少对性能的消耗;

    可以使用的插件比较多;比如underscore,lodash

      lodash中文文档icon-default.png?t=M7J4https://www.lodashjs.com/underscore中文文档icon-default.png?t=M7J4https://www.underscore-js.com/

    二、使用案例

    下面简单用计数器演示下,防抖的操作;

    当在连续点击计数按钮时,不会连续触发计数;

    1. //css代码
    2. <body>
    3. <div id="container">div>
    4. <button>点我button>
    5. <script src="./underscore/underscore.js">script>
    6. <script>
    7. let count = 0;
    8. let container = document.querySelector('#container');
    9. let button = document.querySelector('button')
    10. function countNum(e) {
    11. count++;
    12. container.innerHTML = count;
    13. }
    14. button.onclick = _.debounce(countNum, 300, true);
    15. script>
    16. body>

    三、底层原理简单表示

    1.debounce函数的参数有三个:

    debounce(func,wait,immidiate);

    (1) func 表示事件执行的回调函数;
    (2)wait 表示事件延迟执行的等待时间;

    (3) immediate 表示的是是否立即执行,参数为true时,表示立即执行;为false时,表示在wait等待时间过后执行;

    下面主要对三个参数来分析实现功能:

    (1)延时功能使用 settimeout 来实现;

    (2)this指向问题,在插件中,回调函数的this指向是指向事件的触发者的;所以在做封装时,需要使用call或者apply来改变this指向问题(不改变的化,this是指向window的),因为debounce函数是事件执行的回调函数,所以在debounce中,this指向是指向事件调用者的,所以使用context来保存this,在返回的函数中,使用call来修改func函数的指向;

    (3)event事件的问题,在插件中的event参数是事件的事件的具体类型;在debounce函数中的arguments中是保存了事件调用的信息,所以将argument的事件,使用call方法将参数传递给func;

    1. function debounce(func, wait,immediate) {
    2. let timeout;
    3. return function () {
    4. //在wait时间内,重复触发事件的时候,清除定时器,重新进入wait时间
    5. // console.log(arguments);//arguments参数是具有事件对象的,所以直接将arguments参数传递给func函数
    6. let args = arguments[0];
    7. let context = this;
    8. // console.log(this);//-->指向调用者
    9. clearTimeout(timeout)
    10. //当immediate参数为true时,是立即执行,不进入延迟操作,即进入第一个if判断分支
    11. if (immediate) {
    12. let callNow = !timeout;
    13. timeout = setTimeout(() => {
    14. timeout = null;
    15. }, wait);
    16. //immediate参数设置为true时,(1)刚开始进来timeout还没有生成,即为undefined,取反为true;就会进入下面的立即调用func函数,即立即执行,延时函数开始计时,生成了一个timeout,所以在wait时间内,再次触发事件的时候,callnow不再是true(因为生成了一个timeout,不再是undefined,取反为false),当wait时间过后,重置了timeout = null,所以wait时间后,再次触发事件时,callNow为true(因为timeout置为null了)
    17. if(callNow)func.call(context,args)
    18. } else {
    19. //当immediate参数是false时,不进入延迟操作函数
    20. timeout = setTimeout(function () {
    21. //修改this指向,使用call方法
    22. func.call(context,args)
    23. }, wait);
    24. }
    25. }
    26. }

  • 相关阅读:
    Hive 删除一个字段
    vue重修【005】自定义路由、插槽
    【Luogu】 P4649 [IOI2007] training 训练路径
    Linux查看哪些进程占用的系统 buffer/cache 较高 (hcache,lsof)命令
    从零开始 - Docker部署前后端分离项目(四)
    基于Python完成的配音软件之适用于有声主播
    小样本利器4. 正则化+数据增强 Mixup Family代码实现
    yolov5
    Flutter 创建自己的对话框,不使用任何包!
    你确定不了解下 Java 中反射黑魔法吗?
  • 原文地址:https://blog.csdn.net/weixin_67642008/article/details/126560178