【js基础】防抖、节流、懒加载

353 阅读2分钟

image.png

防抖

现在有这样一个场景,给出一个button,每次点击这个button就会发送请求,像这样:

image.png

image.png

如图,我点击了这个button五次,执行了五次发送请求,乍一看似乎没什么问题,但是,如果在真实的业务场景中,这样发送一起请求,还没有等到结果返回回来就再次发送请求,这样必然会有大量的性能上的开销,并且也会造成返回结果出错的问题。

为了解决这个问题,引入防抖(debounce)的概念: 现在点击这个button,函数并不会立即执行,而是给出这样一个间隔delay,如果在这个间隔以内没有再次触发事件那么就执行函数,如果在这个间隔以内再次触发这个事件,那么就将当前的间隔取消,重新开始计时。


        function Done(){
            console.log("发送请求")
        }

        function debounce(func,delay){
            let timer;
            return function(){
                const context=this;
                const args=arguments;
                clearTimeout(timer);
                timer = setTimeout(function () {
                    func.apply(context,args);//闭包,特别注意this的变化
                },delay);
        }
        }

        btn1.addEventListener("click",debounce(Done,1000));

节流

节流通常指在一段时间内只调用一次事件处理函数,还是已上方发送请求为例,点击这个button会发送一个请求,假设这个函数执行需要花1s的事件,那么在这段事件内我们只希望能够运行这一次函数,避免多次请求。 节流通常有两种写法

//通过setTimeout
function trottle1(func,delay){
          let timer;
          return ()=>{
              if(timer) return;
              let context=this;
              let args=arguments;

              timer=setTimeout(()=>{
                  func.apply(context,args);
                  timer=null;
              },delay);
          }
      }
      
//通过new Date()
 function trottle2(func,delay){
          let pre=0;
          return ()=>{
              let now=new Date();
              if(now-pre>delay){
                  func();
                  pre=now;
              }
          }
      }
      
      document.addEventListener("click",trottle2(Done,1000))
      

懒加载

网页内容如下图所示 image.png

网页如果包含大量图片,并且网速较差,那么就会影响网页渲染速度

image.png

一个优化思想就是调整图片的src属性,只有需要的时候才给出正确的url

我们将所有的src属性改写成data_src,需要的时候再进行修改

//低性能版
//事件累积
 const imgs=document.querySelectorAll("img");

        window.addEventListener("scroll",(e)=>{
            imgs.forEach((img)=>{
                const imgTop=img.getBoundingClientRect.top;//距离dom顶部距离

                if(imgTop<window.innerHeight){
                    const data_src=img.getAttribute("data_src");
                    img.setAttribute("src",data_src);
                }
            })
        })
        
 //视口交叉
        const imgs=document.querySelectorAll("img");

        const observer=new IntersectionObserver((entries)=>{
            entries.forEach((entry)=>{
                if(entry.isIntersecting){
                    const img=entry.target;
                    const data_src=img.getAttribute("data_src");
                    img.setAttribute("src",data_src) ;
                }
            })
        })

        imgs.forEach((img)=>{
            observer.observe(img);
        })