js防抖节流

防抖

我们经常在业务中判断当前用户名是否存在,如代码1所示,如果每次触发input的change事件都向后台请求一次接口,那就非常没有效率,因此我们可以判断用户输入结束后再发送数据。

//代码1
<input type="text" name="userName">
    <script>
 document.querySelector('input').addEventListener('input',function(){
 	console.log('我向后台验证了一次用户名')  
 	//这样每次用户输入值的时候都会请求一次接口,效率低下
})
    </script>

如何判断用户是否结束输入呢?如果input的input事件(keydown事件)n秒内没有被触发,则我们是否可以认为输入已经结束?

//代码2 
//防抖1.0 实现了基本的防抖,但仍然具有问题
//如首次输入后不会立即执行函数,代码3解决了改问题
 document.querySelector('input').addEventListener('input',function(){
            if(timer) clearTimeout(timer);
            var timer=setTimeout(function(){
                    console.log('我向后台验证了一次用户名')
                },1000)
    })
//代码3
//防抖2.0 先立即执行一次函数,然后再防抖
    document.querySelector('input').addEventListener('input',function(){
            if(timer) clearTimeout(timer);
            let im= !timer;
            var timer=setTimeout(function(){
                    console.log('我向后台验证了一次用户名')
                },1000)
            if(im) {console.log('我向后台验证了一次用户名')}
    })

每次防抖都要写一遍是不是感觉很烦,接下来我们一起封装一下防抖吧

//代码4
//防抖3.0 对防抖进行简单的封装
function noShake(callback,time){
            let timer;
            return function(){
            clearTimeout(timer);
            timer=setTimeout(function(){
                   callback(); //执行callback();
                },time)
            }
       }
 document.querySelector('input').addEventListener('input',noShake(function(){
           console.log('我向后台验证了一次用户名')
           console.log(this.value); //会是input的值吗
       },500))

如果忽略没有自动执行的问题,代码4是不是完美的呢?
显然不是,我们忽略了this,还有函数中参数的问题。接下来我们来解决它

//代码5
//防抖4.0 
function noShake(callback,time){
            let timer;
            return function(){
            let s=this,args=arguments; //获取this,和arguments
            clearTimeout(timer);
            timer=setTimeout(function(){
                  callback.apply(s,args); //apply改变this的指向
                },time)
            }
       }
 document.querySelector('input').addEventListener('input',noShake(function(event){
           console.log(this.value);
           console.log(event);   //完美解决
       },500))

代码5的核心理念就是apply改变this指向,(不清楚apply等方法的同学可以点此跳转
接下来我简单分析一下代码5,首先回到代码2

//代码6



//代码2 最初的防抖
document.querySelector('input').addEventListener('input',function(){
            if(timer) clearTimeout(timer);
            timer=setTimeout(function(){
                    console.log('我向后台验证了一次用户名')
                },1000)
    })
    //我们是不是可以把代码2结合代码5改装成下面的形式
   var timer;
    document.querySelector('input').addEventListener('input',function(){
    		function callback(){
    		console.log(this.value) //很明显,当前this指向window
    		}
    		let s=this,args=arguments;  //当前this指向input
            if(timer) clearTimeout(timer);
            timer=setTimeout(function(){
                    callback.apply(s,args); //改变this指向
                },1000)
    })
    //是不是清晰很多
    //代码5中return function(){}作用域的this指向input,而内部的定时器是默认指向window的,所以需要改变this指向。

节流

和防抖差不多,节流是无论用户输入停不停,每隔n秒就执行一次,直接贴代码

//代码7 
//节流
function save(callback,time){
        let start = 0;
        return function(){
            let now = Date.now();   //获取当前时间
            if (now - time > start){  //时间是否已经过去time豪秒。
            callback.apply(this,arguments);
            start = now;   //重置start
            }
        }
        
      }
document.querySelector('input').addEventListener('input',save(function(){
         console.log(this.value)
  },500))


//也可以把时间判断换成boolean变量
function save(callback,time){
		let flag=true;
        return function(){
            if(!flag) return;
            flag=false;
            callback.apply(this,arguments);
            setTimeout(function(){
                flag=true;
            },time)
        }
      }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值