共同点:都用到了setTimeout定时器,都是在指定时间间隔后执行函数,都是为了解决数据时时变化而时时请求导致性能差的问题
区别:防抖在指定时间间隔里再次调用函数,会清除定时器,重新计时,直到在最新的计时时间间隔里没有调用函数,才会执行定时器里的函数。
而节流会在指定时间间隔后会执行一次函数,不会清除定时器而重新计时
防抖缺点:当用户在指定时间间隔里一直操作,那么setTimeout会一直重新计时函数永远不会执行
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
节流缺点:如果用户一直操作,那么setimeout里的函数会在指定时间间隔后都会执行一次,如此反复
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
1. 防抖 (在一定时间间隔内高频触发 只执行最后一次)
防抖策略(debounce)是当事件被触发后,延迟n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。
作用: 高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间内再次触发,则重新计算时间。
1.1防抖的应用场景
1.搜索框等按钮避免用户点击太快,以致于发送了多次请求,需要防抖;
2.手机号、邮箱验证
3.调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖;
4.文本编辑器实时保存,当无任何更改操作一秒后进行保存。
以监听input的值举例:
// 防抖
var input = document.getElementById('input')
input.addEventListener('input', debounce(handle, 1000))
function debounce(fn,delay = 20){
var timer = null;
return function(...args){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.apply(this,args)
}, delay)
}
}
function handle(e){
console.log(e.target.value)
}
2. 节流 (在一定时间间隔内高频触发 只触发一次)
节流策略(throttle),控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。
作用: 高频率触发的事件,在指定的单位时间内,只响应第一次。
2.1 节流的应用场景
1.鼠标连续不断地触发某事件(如点击),单位时间内只触发一次;
2.高频事件:鼠标移动 mousemove 、页面尺寸缩放 resize 、滚动条滚动 scroll 等
3.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断。例如:懒加载;
scroll、mousehover、mousemove等触发频率高的时候
4.浏览器播放事件,每个一秒计算一次进度信息等。
// 节流
var input = document.getElementById('input')
input.addEventListener('input', throttle(handle, 200))
function throttle(fn,delay = 20){
let timer = null;
return function(...args){
if(timer){
return;
}
timer = setTimeout(()=>{
fn.apply(this,args)
timer = null
},delay)
}
}
function handle(e){
console.log(e.target.value)
}
<style>
.box,
.box2 {
width: 100px;
height: 100px;
line-height: 100px;
font-size: 28px;
background-color: pink;
text-align: center;
cursor: pointer;
margin-top: 20px;
}
</style>
<body>
<div class="box">1</div>
<div class="box2">1</div>
<script src="../lodash.min.js"></script>
<script>
/*
防抖节流
1. 防抖(debounce)
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间
使用场景:
1.搜索框
2.手机号、邮箱验证输入检测
2. 节流(throttle)
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数
使用场景:
1.高频事件:鼠标移动 mousemove 、页面尺寸缩放 resize 、滚动条滚动 scroll 等
*/
// 利用防抖实现性能优化
// 需求:鼠标在盒子上移动,里面的数组就会变化 +1
const box = document.querySelector('.box');
let i = 1;
function mouseMove() {
box.innerHTML = i++;
// 如果里面存在大量消耗性能的代码,如 dom操作、数据处理,可能造成卡顿
}
// 添加事件
// box.addEventListener('mousemove', mouseMove)
// 利用 lodash库实现防抖 - 500毫秒之后采取 +1
// 语法: _.debounce(fun,时间)
// box.addEventListener('mousemove', _.debounce(mouseMove, 500))
/*
手写防抖函数
防抖的核心就是利用定时器(setTimeout)来实现
1.声明一个定时器 变量
2.先判断是否有定时器,如果有 清除以前的定时器
3.如果没有定时器则开启定时器,记得存到变量里面
4.在定时器里面调用要执行的函数
*/
function debounce(fn, time) {
let timer = null;
return function (...args) {
// 清除定时器
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, time);
}
}
box.addEventListener('mousemove', debounce(mouseMove, 500))
// 节流
// 需求:鼠标在盒子上移动,不管移动多少次,每隔500ms才 +1
const box2 = document.querySelector('.box2');
let i2 = 1;
function mouseMove2() {
box2.innerHTML = i2++;
// 如果里面存在大量消耗性能的代码,如 dom操作、数据处理,可能造成卡顿
}
// 语法: _.throttle(fun,时间)
// box2.addEventListener('mousemove', _.throttle(mouseMove2, 500))
/*
手写节流函数
节流的核心就是利用定时器(setTimeout)来实现
1.声明一个定时器 变量
2.先判断是否有定时器,如果有 不开启新的定时器
3.如果没有定时器则开启定时器,记得存到变量里面
4.在定时器里面调用要执行的函数,在定时器里面要把定时器清空
*/
function throttle(fn, time) {
let timer = null;
return function (...args) {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, args)
// 定时器里无法清除定时器
timer = null;
}, time);
}
}
box2.addEventListener('mousemove', throttle(mouseMove2, 500))
</script>
</body>