目的:防抖是限制我们的操作,节流是减少我们的操作的。
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率。
防抖:
n 秒后再执行该事件,若在 n 秒内被重复触发,则重新计时。
节流:
n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效。(但是第一次点击始终是生效的,因为第一次的时间是从1970年开始计算的毫秒数)
防抖应用场景:
1、登录(重复点击登录按钮)登录、发短信等按钮避免用户点击太快,导致发送了多次请求,需要防抖。
2、在表单验证中,防抖可以确保在用户输入的过程中不会因为频繁触发验证逻辑而导致性能降低。
3、实时搜索和保存:在文本编辑器或搜索框中实现实时搜索和保存功能时,防抖技术可以确保在用户停止输入一段时间后执行搜索或保存操作,避免了因用户连续输入而频繁触发搜索或保存的问题。
节流应用场景:
1、鼠标不断地点击触发某个事件。
2、拉伸浏览器窗口、监听滚动条的位置。
3、鼠标移动事件:例如实现一个拖拽功能,可以使用节流技术减少鼠标移动事件的处理频率。
4、动画效果:当实现一个基于时间的动画效果时,可以使用节流技术限制动画帧率,降低计算开销。
5、搜索框的下拉列表、希望在单位时间内只触发一次。(如果每次用户键入一个字符就触发这些操作,可能会导致性能问题,特别是当列表很大或网络延迟较高时。)
防抖和节流的封装函数
// 防抖函数
function debounce(func, wait) {
let timeout
return function () {
const context = this
const args = arguments //arguments 是一个类数组对象,它表示传给一个函数的参数。这个对象只在函数内部可用。在函数被调用时,arguments 对象会自动被创建,并包含传递给该函数的参数列表。
if (timeout) clearTimeout(timeout)
timeout = setTimeout(function () {
func.apply(context, args)
}, wait)
}
}
// 节流函数
function throttle(func, delay) {
let lastCall = 0
return function (...args) {
const now = Date.now() //这里获取的毫秒数是很长一段数字,所以第一遍肯定大于delay时间,第一次点击永远是生效的
if (now - lastCall < delay) {
return // 如果上次调用的时间距离现在小于 delay,则直接返回,不执行函数
}
lastCall = now // 更新上次调用的时间
return func.apply(this, args) // 执行函数,并传递正确的上下文和参数
}
}