本文已参与「新人创作礼」活动,一起开启掘金创作之路。
自我介绍:大家好,我是吉帅振的网络日志;微信公众号:吉帅振的网络日志;前端开发工程师,工作4年,去过上海、北京,经历创业公司,进过大厂,现在郑州敲代码。
一、防抖debounce函数
1.定义
n秒后执行,事件触发后延迟执行,输入期间不执行触发操作。无操作及延迟时间过后触发,一般适用于频繁触发的操作。
2.应用场景
输入框中频繁输入内容,搜索或者提交信息;频繁点击按钮,触发某个事件;监听浏览器滚动事件,完成某些特定操作;用户缩放浏览器的resize事件。
3.基本实现
原理是用setTimeout函数达到延迟效果,连续操作时使用clearTimeout函数不断清除定时器,重置延迟时间,阻止连续触发。
let inp = document.getElementById("inp")
var timeout;
inp.oninput = function () {
clearTimeout(timeout)
timeout = setTimeout(() => {
console.log(this.value)
},1000)
}
优化:参数和this指向;增加取消功能;第一次立即执行;返回值
function debounce(fn,delay,immediate=false,resultCallback){
let timer=null
// console.log(this)//window
// 定义控制立即执行的变量,false表示没有执行过
let isInvoke=false
// 真正的处理函数
function _debounce(...args){
// 取消事件执行操作
if(timer) clearTimeout(timer)
// console.log(this)//element元素
if(immediate&&!isInvoke){
const result=fn.apply(this,args)
resultCallback(result)
isInvoke=true
}else{
// 延迟执行
timer=setTimeout(()=>{
const result=fn.apply(this,args)
resultCallback(result)
timer=null
isInvoke=false
},delay)
}
}
// 封装取消请求
_debounce.cancel=function(){
if(timer) clearTimeout(timer)
timer=null
isInvoke=false
}
return _debounce
}
二、节流throttle函数
1.定义
n秒内只执行一次,节流函数是规定一段时间内无法触发,时间过了才触发,即使不断输入值,但只要1秒钟过了,也会触发。
2.应用场景
监听页面的滚动事件;鼠标移动事件;用户频繁点击按钮操作;游戏中的一些设计。
3.基本实现
节流,就是节制的意思,能省就省。写法与防抖函数类似,都是使用定时器,不过它们还是有差别的。
let inp = document.getElementById("inp")
var timeout
let flag = true
inp.oninput = function () {
if (!flag) {
return
}
flag = false
timeout = setTimeout(() => {
console.log(123)
flag = true
}, 1000)
}
优化:节流最后一次也可以执行;增加取消功能;返回值
function throttle(fn,interval,options={leading:true,trailing:false}){
let lastTime=0
const {leading,trailing,resultCallback}=options
let timer=null
function _throttle(...args){
const nowTime=new Date().getTime()
// leading优化
if(!leading&&!lastTime) lastTime=nowTime
let remainTime=interval-(nowTime-lastTime)
if(remainTime<=0){
if(timer){
clearTimeout(timer)
timer=null
}
// 参数优化
const result=fn.apply(this,args)
if(resultCallback) resultCallback(result)
lastTime=nowTime
return
}
// 优化trailing
if(!timer&&trailing){
timer=setTimeout(()=>{
// 参数优化
const result=fn.apply(this,args)
if(resultCallback) resultCallback(result)
timer=null
lastTime=!leading?0:new Date().getTime()
},remainTime)
}
}
_throttle.cancel=function(){
if(timer) clearTimeout(timer)
timer = null
lastTime = 0
}
return _throttle
}