JS节流与防抖
对JS节流和防抖的理解
- 防抖与节流本质上是优化高频率执行代码的一种手段。浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
- JS节流和防抖的区别,举个公交车站的栗子:
将时间段设为5分钟,有人上车代表触发事件- 节流:假设司机最先上车,那么五分钟内,不管有没有人再上车,只要过了这个五分钟就会发车
- 防抖:等到最后一个人上车后的5分钟没人再上车了才会发车,如果五分钟内有人上车,那么会重新计算五分钟
JS的节流throttle
- 原理:在持续触发某事件时,一定的时间内只会执行一次函数,目的是减少一定事件内的触发频次
- 应用场景:鼠标连续不断地触发某事件(如点击),单位时间内只触发一次;监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断。例如:懒加载;浏览器播放事件,每个一秒计算一次进度信息等。
代码实现:
- 基础版节流
<script>
/*
节流:短时间当中 频繁地触发某事件 在一定时间当中 只执行一次
*/
let startTime = 0 // 开始的时间 => 0
document.onmousemove = function(e){ //在网页中绑定鼠标移动事件
// 获取当前时间戳
let nowTime = +new Date()
//这里时间段为1000ms 意味着频繁移动鼠标时 只会隔1000ms后才触发事件
if(nowTime - startTime < 1000){
return
}
// 下一次的开始时间就是上一次的结束时间
startTime = nowTime
// 业务代码
console.group("执行一次");
console.log(e);
console.groupEnd()
}
</script>
- 封装版节流
<body>
<div class="box"></div>
<script>
/*
节流:短时间当中 频繁地触发某事件 在一定时间当中 只执行一次
*/
// fn => 业务代码
// 1000 => 节流时间
const box = document.querySelector(".box")
box.onmousemove = window.throttle(fn,1000)
// 业务代码
function fn(e){
console.group("执行一次")
console.log(e);
console.log(this);
console.groupEnd()
}
// 封装节流
function throttle(fn,time){
let startTime = 0 //开始时间 => 0
return function(e){
// 鼠标移动 => 就执行这里的代码
// 当前时间
let nowTime = +new Date()
if(nowTime - startTime < time){
return
}
// 下一次的开始时间就是上一次的结束时间
startTime = nowTime
fn.call(this,e) // 如果不改变this执行那么指向window 应该让它指向事件源
}
}
</script>
</body>
- 企业版节流 引入lodash.js文件
<script src="./lodash.js"></script>
<script>
// 业务代码
function fn(e){
console.group()
console.log(e);
console.log(this);
console.groupEnd
}
// 节流
document.onmousemove = _.throttle(fn, 1000)
</script>
JS的防抖debounce
- 原理:当频繁触发某事件时,若在设定时间内重复触发,会重新开始计时,直到过了设定的时间没有再次触发了,事件才会处理函数一次
- 应用场景:登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖;调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
代码实现:
- 封装版防抖
<body>
<input type="text" placeholder="请输入您的姓名">
<script>
// 防抖 => 短时间频繁触发某事件 一定时间内只执行最后一次
const inpEle = document.querySelector("input")
// 防抖处理
inpEle.oninput = debounce(fn,1000)
// 防抖
function debounce(fn,time){
let timer = null
return function(e){
if(timer != null){ //存在定时器则清除 意味着重新计时
clearTimeout(timer)
}
timer = setTimeout(()=>{ //设置定时器
fn.call(this,e) //让this指向事件源
},time)
}
}
// 业务代码
function fn(e){
console.group("防抖,执行一次")
console.log(e);
console.log(this);
console.groupEnd()
}
</script>
</body>
- 企业版防抖 引入lodash.js文件
<body>
<script src="./lodash.js"></script>
<input type="text" placeholder="请输入您的姓名">
<script>
const inpEle = document.querySelector("input")
// 企业版防抖
inpEle.oninput = _.debounce(fn, 1000)
// 业务代码
function fn(e){
console.group("防抖")
console.log(e);
console.log(this);
console.groupEnd()
}
</script>
</body>
lodash.js文件可以通过Boot CDN官网进行下载或者直接请求网络链接
使用方法进入Lodash官网搜索防抖和节流的使用