js中的防抖和节流深入理解

99 阅读2分钟

背景

  • 浏览器的resize、scroll、keypress、mousemove等事件被触发以及监听表单输入值等类似的频繁操作某个函数方法的场景,会极大的浪费资源,消耗前端性能。
  • 为了优化体验,需要对这类事件进行调用次数的限制,对此我们通常采用防抖和节流的方式来减少调用频率

定义

  • 防抖:t秒后再执行该事件,若在t秒收重复触发,则重新计时。
  • 节流:t秒内只执行一次,若在t秒内触发多次,只执行一次。

原理

  1. 防抖: 写一个input标签,想监听输入的值完成之后再打印 image.png 显示效果如下,这个时候每输入一个字符都会去进行打印,显然不是想要的效果。

image.png 处理方法如下

const inputDom = document.querySelector('input');
// 运用闭包函数的特点
function debounce(fn, delay){
    let timer = null;
    return function(){
        // 如果触发过一次,清除定时器重新等待
        if(timer){
            clearTimeout(timer);
        }
        // 如果不是箭头函数,需要手动改变this的指向,要不然this是全局window
        timer = setTimeout(()=>{ 
            fn();
        }, delay);
    }
}
inputDom.oninput = debounce(function(){
    console.log(this.value);
}, 500)

效果如下

image.png 应用场景

  • 搜索框搜索输入,只需用户最后一次输入完成,再与后台交互
  • 手机号、邮箱输入验证
  • 窗口大小resiz,只需窗口调整完成再调整大小,防止重新渲染。
  1. 节流 定义一个高度大于浏览器高度的dom元素,这个时候浏览器会显示滚动条,监听浏览器的滚动事件,会发现滚动一下打印了n次,对浏览器消耗很大
<div style="height: 10000px;width: 100%;">测试滚动</div>
<script>
    const divDom = document.querySelector('div');
    window.onscroll = function(){
        console.log('滚动');
    };
</script>

image.png 处理方法

const divDom = document.querySelector('div');
function throttle(fn, delay){
    let flag = true;
    return function(){
        if(flag){ 
            setTimeout(()=>{
                fn();
                flag=true
            }, delay);
        }
        flag=false;
    }
}
window.onscroll = throttle(function(){
    console.log('滚动');
}, 500);

滚动4次,打印4次

image.png 应用场景

  • 滚动加载,加载更多或者滚动底部监听
  • 搜索框,搜索联想功能