防抖与节流
首先什么是防抖,比如说现在有一个input标签,想通过他搜索一个东西,例如前端工程师,输入完成0.5秒后会发送一个请求,获得到前端工程师搜索的结果,展示到界面,下面是对应的代码,以及运行结果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text">
<script>
let inp=document.querySelector('input')
function inputChange(){
console.log(this.value)
}
inp.οninput=inputChange//输入时会触发
</script>
</body>
</html>
相当于每输入一次,事件都会被触发一次,与此同时和后台进行一次数据的交互,这样带来的副作用就是会影响性能,那如何在用户频繁触发事件时,做出合理的请求呢,这里就需要用到防抖函数,使其在规定间隔时间内,连续输入的情况下,事件不被触发,只有在输入完最后一个字后触发该事件,
这里我们先写一个简单的小栗子,之后再利用闭包去封装一个防抖的debounce的方法
let inp=document.querySelector('input')
let timer=null;//在全局环境下定义一个计时器的变量
function inputChange(){
if(timer!==null){
clearTimeout(timer)
}
timer=setTimeout(()=>{
console.log(this.value)
},1000)
}
inp.οninput=inputChange
也就是说在一秒内再连续输入事件就不会被触发,只在输入完成时触发最后一次
这就像码头上的船每隔十分钟开走一次,但这十分钟内只要有新的人上船,就会重新开始计时;
这里面只有console.log(this.value)是业务相关的代码,现在只有一行看不出什么问题,一旦业务变得复杂,过长业务的代码与防抖代码混在一起就会不利于维护,那怎末来解决这个问题呢?就是我上面提到的利用闭包来封装一个防抖函数!
let inp=document.querySelector('input')
function inputChange(){
console.log(this.value)
}
inp.οninput=debounce(inputChange,1000)//用防抖来控制这个事件
function debounce(fn,delay){//fn是形参传进来的是业务的逻辑
let timer=null;
return function (){
if(timer!==null){
clearTimeout(timer)
}
timer=setTimeout(()=>{
fn.call(this)
},delay)
}
}
这里debounce是一个外部函数,返回值是一个内部函数,内部函数使用了外部函数的变量timer
至于这里为什么使用call(this)呢?通过打印inputChange的this.value,发现这个this.value是undefined,只打印this的话输出的是一个全局对象,但我们要的不是全局对象,inputChange传入到debounce中执行的是fn();如何让这里的指针指向inp呢?在定时器中打印this,输出如图所示的内容,所以内部函数的this指向inp,我们可以通过call来改变谁来调用fn
节流
节流可以控制执行的次数
<style>
body{
height:2000px;
}
</style>
<body>
<script>
window.οnscrοll=function(){
console.log(123)
}
</script>
</body>
当在浏览器拖动滚动条时,控制台会不断输出123
<style>
body{
height:2000px;
}
</style>
<body>
<script>
function scrollChange(){
console.log("小钟要长高")
}
window.οnscrοll=throttle(scrollChange,1000)
function throttle(fn,delay){
let trigger=true
return function(){
if(trigger){
setTimeout(()=>{
fn();
trigger=true
},delay)
}
trigger=false
}
}
</script>
</body>
节流函数应用场景
防抖应用场景:输入框
节流应用场景:比如窗口调整、页面滚动、抢购和疯狂点击等会用到节流。
节流与防抖的区别:
节流与防抖的前提都是某个行为持续地触发,不同之处只要判断是要优化到减少它的执行次数还是只执行一次就行。