我该怎么优化?防抖?节流?
节流与防抖是两种用于控制事件触发频率的技术,它们经常用于前端开发中,既不会影响用户的体验,又能优化用户交互和提升浏览器的性能。就比如滚动鼠标和拖动浏览器边界、键盘输入和点击事件来改变窗口大小时,都涉及了节流和防抖。那么它们到底是什么,怎么是实现的呢?
一、节流
技术应用场景
保证在特定的delay时间内,某个功能函数只执行一次。在处理高频触发的事件(如窗口滚动、调整大小、鼠标移动)时特别有用,这些事件在改变的内容很少时,却会高频触发,让浏览器会过度的计算和重绘。
如何实现
<body>
<div class="row">
没有节流的input <input type="text" id="inputa">
</div>
<div>
节流后的input <input type="text" id="inputc">
</div>
<script>
const inputa = document.getElementById('inputa')
const inputc = document.getElementById('inputc')
const ajax = (content)=>{
console.log(`ajax request ${content}`)
}
//节流功能
const throttle = (func,delay)=>{
let last,deferTimer //自由变量
return (args)=>{
// 当前时间,隐式类型转换
let now = +new Date()
if(last && now < last + delay){
//避免触发
clearTimeout(deferTimer)
deferTimer = setTimeout(() => {
last = now
}, delay);
}else{
last = now // 第一次时间
func(args) // 先执行一次
}
}
}
inputa.addEventListener('keyup',(e)=>{
ajax(e.target.value)
})
let throttledFunc = throttle(ajax,1000)
inputc.addEventListener('keyup',(e)=>{
let value = e.target.value
throttledFunc(value)
})
</script>
</body>
- 我们定义
ajax
函数来模拟耗时性任务,并在控制台打印提示信息来直观观察节流功能。 - 定义节流函数
throttle
,返回闭包函数,节流函数中接收要执行的函数与延迟时间,定义自由变量(调用时能找到闭包中的变量):上次函数执行的时间,定时器id。 - 闭包函数中,第一次调用进入
else
判断,立即执行func
,并在之后的每次调用时(高频事件触发时),如果距离上次执行没有delay
时间的话,不会执行func
,并且清除定时器,更新当前时间,确保下次距离上次执行没有delay
时间时,func
依然不会触发。
当用户在输入框中快速输入文字时,使用节流的输入框会有效的减少事件处理器的调用次数,节省了计算资源,提高了用户体验。
防抖
技术应用场景
确保某个功能函数在一系列的连续触发事件中,只在最后一次事件结束后执行。在处理键盘输入或者点击事件中作用很明显,因为它确保了只有在用户真正停止了操作后才进行逻辑的处理。
Goole Suggest: 当用户在Google
搜索框中开始输入查询词时,Google Suggest
会预测可能的搜索查询,并实时显示一系列建议供用户选择。
如何实现
- 启动
json-server
模拟后端数据。 -
npm i json-server
-
- 创建
JSON
格式数据作为数据源。创建JSON文件,如db.json
- 创建
-
- 项目目录中打开
pack.json
,script对象添加脚本。
- 项目目录中打开
-
npm run dev
(脚本名称)

- 定义
debounce
函数,接收要防抖处理的函数func
,延迟事件delay
。 - 返回的闭包函数会清除定时器并重新设定定时器,目的是每次事件触发时都清除掉定时器,不让函数触发,直到在最后一次事件触发调用功能函数(如用户最后一次输入)后,过delay时间,执行func函数。
<body>
<div>
没有防抖的input
<input type="text"
id="unDebounce"
placeholder="请您要搜索的用户名"
>
</div>
<div>
防抖后的input
<input type="text"
id="debounce"
placeholder="请您要搜索的用户名"
>
</div>
<script>
// 不加防抖的
const inputa = document.getElementById('unDebounce')
const inputb = document.getElementById('debounce')
function handleNameSearch(e){
const value = e.target.value
fetch("http://localhost:3000/users")
.then(res=>res.json())
.then(data=>{
const users = data
const filterUsers = users.filter(user =>{
return user.name.includes(value)
})
console.log(filterUsers);
})
}
//闭包功能函数
function debounce(func,delay){
return function(args){
clearTimeout(func.id)
//函数是对象, id挂在func上
func.id = setTimeout(function(){
func(args)
},delay)
}
}
const debounceNameSearch = debounce(handleNameSearch,500)
inputa.addEventListener('keyup',handleNameSearch)
inputb.addEventListener('keyup',debounceNameSearch)
</script>
</body>
现在你能在某个场景中正确使用防抖、节流了吗?你该怎么优化类似的功能呢?防抖?节流?
转载自:https://juejin.cn/post/7388338139633352755