防抖的定义:前面的所有触发都被取消。最后一次执行在规定时间后才会触发,也就是说如果连续快速的触发,只会执行一次。
节流的定义:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发。
防抖:用户触发时间过于频繁,只要最后一次
用户在输入框输入内容停下来不再输入的0.5秒后,控制台才打印出来输入的内容
<script>
let fangdou=document.querySelector("input")
let t=null;
fangdou.oninput=function(){
if(t!==null){
//t!=null先清除前边建的定时器
clearTimeout(t)
}
//再开一个定时器
t=setTimeout(()=>{
console.log(this.value)
},500)
}
</script>
在上面的计时器方法实现的防抖我们可以看到防抖的逻辑和业务逻辑都混在了一起,不利于后期维护,接下来用闭包的方法封装一个防抖函数
<script>
let fangdou=document.querySelector("input")
//业务处理:这里调用封装的debounce进行防抖,并将函数和延时时间传给了debounce函数
fangdou.oninput=debounce(function(){
console.log(this.value)
},500)
//debounce函数进行防抖算法处理
function debounce(fn,delay){//外部函数
let t=null;//内部函数使用了外部函数的的变量,因为闭包,所以这个变量不会被销毁
return function(){//内部函数
if(t!==null){
//t!=null先清除前边建的定时器
clearTimeout(t)
}
//再开一个定时器
t=setTimeout(()=>{
fn.call()//不写.call时this指向了window对象,用call改变了this指向,指向了当前调用的input
},delay)
}
}
</script>
节流:控制执行次数
通过滚动滚动条,控制123打印的次数
<style>
body{
height:2000px
}
</style>
<scrpit>
let flag=true;
window.onscroll=function(){//滚动
if(flag){ //为true执行
setTimeout(()=>{
console.log("123")
flag=true //定时器执行了就改为true,使得如果还在滚动的话还能继续打印
},500)
}
flag=false //在每一个0.5秒后不再操作滚动条就会变为false
}
</script>
<style>
body{
height:2000px
}
</style>
<scrpit>
//业务处理:这里调用封装的throttle进行节流,并将函数和延时时间传给了throttle函数
window.onscroll=throttle(function(){
console.log("123")
},500)
function throttle(fn,delay){
let flag=true;//内部函数使用了外部函数的的变量,因为闭包,所以这个变量不会被销毁
return function(){//滚动
if(flag){ //为true执行
setTimeout(()=>{
fn()
flag=true //定时器执行了就改为true,使得如果还在滚动的话还能继续打印
},delay)
}
flag=false //在每一个0.5秒后不再操作滚动条就会变为false
}
}
</script>
防抖和节流本质上是优化高频率执行代码的一种手段, 如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能,为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用throttle(防抖)和debounce(节流)的方式来减少调用频率。
防抖在连续的事件,只需触发一次回调的场景有:
①搜索框搜索输入内容,只需用户最后一次输入完,再发送请求
②手机号验证码、邮箱验证码获取
③窗口大小resize,只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流在间隔一段时间执行一次回调的场景有:
①滚动加载,加载更多或滚到底部监听
②搜索框的模糊查询功能
③ 鼠标不断点击触发,mousedown(单位时间内只触发一次)