1. 节流
一段时间内只能触发一次,如果这段时间内触发多次事件,只有第一次生效会触发回调函数,一段时间过后才能再次触发(n秒内第一次生效)
例如:轮播图 98k点击一次射击一次换子弹期间不能射击 王者荣耀英雄技能冷却
代码实现:
function throttle(fn,delay){
let flag = true;
return function(){
if(flag){
flag = false;
setTimeout(() =>{
flag = true
},delay)
return fn()
}
}
}
效果:即使一段时间内大量触发同一事件,在回调函数执行一次之后,该回调函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。
2. 防抖
在事件被触发时,延迟n秒后再触发回调函数,如果n秒内又触发了事件,则会重新开始计算时间(n秒内最后一次生效)
例如:王者回城 输入框的搜索功能 页面resize事件
代码实现:
function debounce(fn,delay){
let timer = null;
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay)
}
}
效果:在某个时间段内,不管你触发多少次事件,只执行一次回调函数。
3. 事例
写一个例子将上面的节流和防抖都用上💡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box{
width: 90%;
height: 200px;
outline: blanchedalmond 1px solid;
margin: 10px auto;
padding: 20px;
box-sizing: border-box;
}
.container{
height: 60px;
margin-top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.aa{
width: 60px;
height:60px;
text-align:center;
color: white;
}
.aa>div{
width: 60px;
height: 40px;
}
#target{
background-color: coral;
}
#home{
background-color: aqua;
}
#bullet{
width: 60px;
}
#bullet>div{
position: absolute;
left: calc(5% + 20px);
width: 30px;
height: 10px;
background-color: dimgrey;
}
#hanxin{
text-align: center;
position: relative;
left: 0px;
}
.send{
animation: move 1s linear;
animation-fill-mode: forwards;
}
@keyframes move
{
to {left: calc(90% - 35px);}
}
</style>
</head>
<body>
<div class="box">
<h2>节流</h2>
<button id="shoot">发射</button>
<text id="text1">子弹已就绪</text>
<div class="container">
<div id="bullet">手枪
</div>
<div class="aa" id="target">目标
<div></div>
</div>
</div>
</div>
<div class="box">
<h2>防抖</h2>
<button id="back">回城</button>
<text id="text2">英雄未回城</text>
<div class="container">
<div id="hanxin">韩信</div>
<div class="aa" id="home">泉水
<div></div>
</div>
</div>
</div>
</body>
<script>
let bullet = document.querySelector('#bullet');
let hanxin = document.querySelector('#hanxin');
let shoot = document.querySelector('#shoot');
let back = document.querySelector('#back');
let text1 = document.querySelector('#text1')
let text2 = document.querySelector('#text2')
// 节流
// 两个参数分别是 要执行的回调函数,间隔时间
function throttle(fn,delay){
let flag = true;
return function(){
if(flag){
flag = false;
text1.textContent = '子弹上膛中'
setTimeout(() =>{
flag = true
text1.textContent = '子弹已就绪'
},delay)
return fn()
}
}
}
// 防抖
function debounce(fn,delay){
let timer = null;
return function(){
if(text2.textContent === '英雄已回城'){
return alert('韩信已经回城了,刷新页面再来试一下吧!')
}
if(timer){
clearTimeout(timer)
}
text2.textContent = '英雄回城中'
timer = setTimeout(fn,delay)
}
}
// 射击事件
function shooting(){
var zd = document.createElement("div")
bullet.appendChild(zd).classList.add('send')
}
// 回城事件
function goHome(){
hanxin.style.left = 'calc(100% - 60px)';
text2.textContent = '英雄已回城'
}
let a = throttle(shooting,2000)
shoot.addEventListener('click',a)
let b = debounce(goHome,3000)
back.addEventListener('click',b)
</script>
</html>
效果图:
可以看到子弹射出后,要等待一段时间⏱才能,再次射击。
当韩信回城时,我们再次点击回城按钮,会重新计算回城时间⏱
4. 总结
- 节流是触发事件后,立即执行回调,一段时间过后才能再次触发,在这期间内无论触发多少次事件都不会执行回调(类似英雄技能冷却)。
- 防抖是触发事件后,过一段时间再执行回调,在这期间再次触发事件,会重新计算时间(类似英雄回城)。
- 节流和防抖的作用都是防止函数多次调用。