防抖(debounce)
单位时间内,频繁触发事件,只执行最后一次。如果在n秒内又触发了事件,则会重新计算函数执行时间。
例子:王者荣耀回城,只要被打断就需要重新来
使用场景:
1)搜索框搜索输入。只需用户最后一次输入完,再发送请求
2)手机号、邮箱验证输入检测
利用防抖来处理-鼠标滑过盒子显示文字
要求:鼠标在盒子上移动,鼠标停止500ms之后,里面的数字才会变化+1
实现方式:
1.lodash提供的防抖来处理
语法:_.debounce(func,[wait=0],[options=])
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="box" style="background-color: aliceblue;width: 200px;height: 200px;"></div>
<script src="./lodash/lodash.js"></script>
<script>
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', _.debounce(mouseMove, 50))
</script>
</body>
</html>
2.手写一个防抖函数来处理
核心思路:防抖的核心就是利用定时器(setTimeout)来实现
1)声明一个定时器变量
2)当鼠标每次滑动都先判断是否有定时器了,如果有定时器先清除以前的定时器
3)如果没有定时器则开启定时器,记得存到变量里
4)在定时器里面调用要执行的函数
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="box" style="background-color: aliceblue;width: 200px;height: 200px;"></div>
<script>
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
function debounce(fn, t) {
let timer
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn()
}, t)
}
}
box.addEventListener('mousemove', debounce(mouseMove, 50))
</script>
</body>
</html>
节流(throttle)
单位时间内,频繁触发事件,只执行一次
例子:王者荣耀技能冷却,期间无法继续释放技能
使用场景:高频事件:鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll
利用防抖来处理-鼠标滑过盒子显示文字
要求:鼠标在盒子上移动,不管移动多少次,每隔500ms才+1
实现方式:
1.lodash提供的节流来处理
语法:_.throttle(func,[wait=0],[options=])
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="box" style="background-color: aliceblue;width: 200px;height: 200px;"></div>
<script src="./lodash/lodash.js"></script>
<script>
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
box.addEventListener('mousemove', _.throttle(mouseMove, 50))
</script>
</body>
</html>
2.手写一个节流函数来处理
核心思路:节流的核心就是利用定时器(setTimeout)来实现
1)声明一个定时器变量
2)当鼠标每次滑动都先判断是否有定时器了,如果有定时器则不开启新定时器
3)如果没有定时器则开启定时器,记得存到变量里
4)在定时器里面调用要执行的函数,把定时器清空
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="box" style="background-color: aliceblue;width: 200px;height: 200px;"></div>
<script>
const box = document.querySelector('.box')
let i = 1
function mouseMove() {
box.innerHTML = i++
}
function throttle(fn, t) {
let timer = null
return function () {
if (!timer) {
timer = setTimeout(function () {
fn()
timer = null//在setTimeout中是无法删除定时器的,因为定时器还在运作,所以使用timer=null而不是clearTimeout(timer)
}, t)
}
}
}
box.addEventListener('mousemove', throttle(mouseMove, 50))
</script>
</body>
</html>
案例:页面打开,可以记录上一次的视频播放位置
两个事件:
1)ontimeupdate事件在视频/音频(audio/video)当前的播放位置发送改变时触发
2)onloadeddata事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的下一帧时触发
const video = document.querySelector('video')
video.ontimeupdate = _.throttle(() => {
localStorage.setItem('currentTime', video.currentTime)
}, 1000)
video.onloadeddata = () => {
video.currentTime = localStorage.getItem('currentTime') || 0
}