防抖
概念
持续触发事件,规定时间内没有再次触发,执行一次,规定时间内再次触发,重新开始延时,只会响应一次触发
代码实现
非立即执行---只响应最后一次----input框输入搜索
const debounce = function (delay,cb){
// 下一次触发,需要取消上一次的timer,所以需要保留上一次的timer,使用闭包实现
let timer
return function(value){
// 存在timer,取消并开启一个新的
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
cb(value)
},delay)
}
}
立即执行----只响应第一次----表单提交或点击按钮发起请求
const debounceImmediate = function(delay,cb){
let timer
return function(value){
let isFirst = !timer
if(isFirst){
cb(value)
}
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
timer = null
},delay)
}
}
案例演示:
<h1>非立即执行版本案例</h1>
搜索:<input id="input"/>
<hr>
<h1>立即请求版本案例</h1>
<button id="btn">提交</button>
// input输入实时搜索
const inputFn = function(value){
console.log(`发起请求,搜索key为${value}`)
}
let inputDebounce = debounce(1000,inputFn)
document.querySelector('#input').addEventListener('input',(event)=>{
inputDebounce(event.target.value)
})
// 点击按钮提交表单
const btnFn = function(){
console.log('正在提交表单')
}
let btnDebounce = debounceImmediate(1000,btnFn)
document.querySelector('#btn').addEventListener('click',btnDebounce)
应用场景
- 点击按钮发送请求时,需要使用debounce来防止用户疯狂点击按钮造成重复提交请求
- 页面resize
- search搜索联想,节约请求资源
节流
概念
持续触发事件,保证在规定时间内,只执行一次事件处理函数,时间间隔内,响应一次触发,控制频率
代码实现
借助定时器实现
const throttle = function(delay,cb){
let timer
return function(){
// timer 存在不做任何处理
if(timer) return
timer = setTimeout(() => {
cb()
// 执行完毕后恢复timer初始值
timer =null
}, delay);
}
}
还可以借助时间戳来实现
const throttleByTime = function(delay,cb){
let time
// 是否第一次触发标识--为了保证第一次执行回调函数是在第一次点击后的delay毫秒时刻
let first = true
return function(){
// 第一次点击,选取当前时间赋值给time
if(first){
time = Date.now()
first = false
}
if(Date.now()-time>=delay){
time = Date.now()
cb()
}
}
}
案例演示:
<style>
.father{
width:300px;
height:30px;
background-color:green;
}
.son{
height:100%;
width:0;
background-color: red;
}
</style>
<div class="father">
<div class="son"></div>
</div>
<button id="btn">增加进度</button>
let sonDiv = document.querySelector('.son')
const btnFn = function () {
let currentWidth = sonDiv.style.width.split('%')[0]
if(currentWidth<100){
sonDiv.style.width =Number(currentWidth)+5+'%'
}
console.log(currentWidth)
}
let fn = throttleByTime(1000,btnFn)
document.querySelector('#btn').addEventListener('click',fn)
点击一次按钮,进度增加5%,但是使用节流处理后,不管你手速多快,也只会一秒执行一次函数,增加5%,难道这就是我抢不到演唱会门票的原因吗?
应用场景
- 监听滚动事件
- input实时搜索