阅读 68

前端性能优化经典:javascript防抖节流

大家好,我是前端岚枫,一枚二线城市的程序媛,今天主要跟大家分享我整理的前端的一些性能优化,js防抖节流,它是项目比较常见的性能优化方案,也是面试中常遇到的问题。希望下面文章对大家有所帮助。

我们在做项目过程中会用一些方法,比如防抖、节流、去重、深拷贝浅拷贝、数组扁平化、乱序、柯里化等经典。 我们平时在开发的时候,会有很多场景会频繁触发事件,比如搜索框实时发请求,onmousemove,onscroll oninput resize onkeyup keydown等等,我们需要优化这些高频率事件,降低代码执行频率,这时候 优化高频率事件onscroll oninput resize onkeyup keydonw...降低代码执行频率,这个时候就需要用到函数防抖和函数节流了。 比较常见的两个库就是underscore 和lodash,这个javascript中都有防抖节流的函数, 想了解更多可以参考以下文档地址。 underscore文档地址: underscorejs.net/#throttle lodash文档地址: www.lodashjs.com/docs/lodash… 网页展示的过程: image.png

  • javascript动画/往页面里添加一些DOM元素

  • style确定每个DOM应该用什么样式规则

  • Layout布局,计算最终显示的位置和大小

  • Paint绘制DOM,在不同行的层次上绘制

  • Composite渲染层合并

用户scroll和resize行为会导致页面不断的重新渲染,如果绑定的回调函数中大量操作dom也会出现页面卡顿 优化方案:

一、函数节流(Throttle)

image.png

节流就是保证一段时间内,核心代码只执行一次

打个比方:水滴积攒到一定重量才会下落

1. 简易节流函数

//节流我们快速点击 我可以配置1s内的点击算一次 <button>快速点击</button>  function throttle(func, wait){     let  previous = 0; //上一次的默认值     return function(){         let now = Date.now()         if(now - previous> wait){             func.apply(this, arguments);             previous = now         }     } } function logger(e){ console.log('log -----') } btn.addEventListener('click',throttle(logger, 1000))function throttle(method, dalay){ 复制代码

2. 完整版:

function throttle(func, wait,options){     // trailing最后一次应该触发(默认触发)     //leading 延迟执行     let args, context, previous = 0,timeout = null;     let later = function(){         previous = options.leading === false ? 0 : Date.now();         func.apply(context, args)     }     let throttled = function (){         args = arguments;         context = this;         let now = Date.now(); //现在时间         if(!previous && options.leading === false){             previous = now         }         let remaning = wait - (now-previous);         if(remaning <= 0) { //第一次             if(timeout){}             clearTimeout(timeout)             timeout = null            func.apply(this, args)             previous = now         } else if(!timeout && options.trailing !== false) {             timeout = setTimeout(later, remaning)         }     }     return throttled }   function logger(){       console.log('logger')   }   btn.addEventListener('click',throttle(logger, 1000,{trailing: true, leading: false})) 复制代码

原理:如果持续触发事件,每隔一段时间,只执行一次事件

3. 应用场景

  1. DOM元素拖拽功能实现

  2. 计算鼠标移动距离

  3. 监听scroll滚动事件

二、防抖(Debounce)

image.png

防抖就是一段时间内结束后,才能触发一次事件,如果一段时间结束内再次触发事件,就会重新计算时间

打个比方:你在电梯中,门快要关了,突然有人准备上来。电梯并没有改变楼层,而是再次打开电梯门,电梯延迟了改变楼层的功能,但是优化了资源。

1. 引入underscor库,体验debounce

<!DOCTYPE html> <head>     <meta charset="UTF-8">     <title>防抖</title>     <style>         #container{             width: 200px;             height: 100px;             border: 1px solid red;             text-align: center;             line-height: 100px;         }     </style> </head> <body>     <!--防抖-->     <div id="container"></div>     <script src="https://unpkg.com/underscore@1.13.1/underscore-umd-min.js"></script>     <script>                let  btn = document.getElementById('#container');        let count = 0;        function doSomeThing(){            // 可能会做回调或者Ajax请求             container.innerHTML = count++;                   }      // 高阶函数 防抖      container.onmousemove = _.debounce(doSomeThing, 300);      // 防抖:      //事件响应函数(doSomeThing)在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间;当预定的时间内没有再次调用该函数,则执行响应doSomeThing函数     </script> </body> </html> 复制代码

说明:事件响应函数(doSomeThing)在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间;当预定的时间内没有再次调用该函数,则执行响应doSomeThing函数

2. 简易防抖函数

function debounce(func, wait, immediate){       let timeout       return function(){           clearTimeout(timeout);           if(immediate){               let callNow = !timeout               if(callNow){                 func.apply(this,arguments)               }           }           timeout = setTimeout(()=>{               func.apply(this,arguments)               timeout = null           }, wait)       }   }  function logger(e){ console.log('log -----') } btn.addEventListener('click',debounce(logger, 1000, true)) 复制代码

3. 完整版本:

 /**    * 防抖的函数    *     * @param {*} func 要调用的函数    * @param {*} wait  延迟时间    * @param {*} immdeidate  是否立即执行    * @returns     * by 前端岚枫    */   function debounce(func, wait, immdeidate){     var timeout, result;         var debounced = function(){         //改变执行函数内部this的指向         var context = this;         var args = arguments         if(timeout) {             clearTimeout(timeout)         }         if(immdeidate){              let callNow = !timeout;           timeout = setTimeout(()=>{               timeout = null;           }, wait);           //立即执行           if(callNow) {             result =  func.apply(context,args)           }                  } else {          timeout = setTimeout(function(){              func.apply(context,args)          }, wait);          }          return result              };     debounced.cancel = function(){         clearTimeout(timeout)         timeout = null     }        return debounced; } 复制代码

4. 应用场景

  1. scroll事件滚动

  2. 浏览器窗口的缩放resize事件

  3. 搜索框输入查询的时候

  4. 表单验证

  5. 按钮的提交事件


作者:前端岚枫
链接:https://juejin.cn/post/7026353735311818760


文章分类
前端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐