本文主要介绍了防抖节流的基本知识和使用过程。文章中不仅会讲述原来使用的防抖或节流方式,还会带来新的一种封装方式,使用起来更简单、更清晰。 在前端的开发过程中,在涉及到与用户交互的过程中是基本上都是需要处理的,常规操作就是在对应位置加上防抖或者节流。 加上防抖或者节流的作用:一是为了防止用户频繁操作;二是为了节约一定的服务器资源,减少资源浪费的情况。
节流(Throttle)
节流是指在一段时间内,无论事件被触发多少次,都只执行一次处理函数。
应用场景: 页面滚动,鼠标点击
示例代码:
// 定时器闭包实现
function throttle(func, delay:1000) {
let _time = null;
return function () {
let context = this;
let args = arguments;
if (_time) return
_timer = setTimeout(() => {
clearTimeout(_timer)
_timer = null
// 改变函数内部的值
func.apply(context, args);
}, delay)
}
}
// 时间戳闭包实现
function throttle(func, delay:1000) {
let lastTime = 0;
return function () {
let context = this;
let args = arguments;
let now = Date.now();
if (now - lastTime >= delay) {
// 更新时间
lastTime = now;
func.apply(context, args);
}
}
}
// 使用
let count = 0
throttle(() => count += 1, 1000)
防抖(debounce)
防抖是指当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
应用场景: 搜索框、窗口大小调整
示例代码:
// 定时器不闭包实现
function debounce(func, delay:1000) {
let timer = null;
clearTimeout(timer);
timer = setTimeout(() => {
func;
}, delay);
}
// 定时器闭包实现
function debounce(func, delay:1000) {
let timer = null;
return function () {
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
func.apply(context, args);
}, delay);
}
}
// 使用
let count = 0
debounce(() => count += 1, 1000)
提升(响应式的防抖和节流)
在Vue3中,可以使用customRef来实现响应式的防抖与节流
customRef 可以用来创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
执行过程: 当数据value发生了变化,就会触发set函数,set接收变化后的数据newValue,newValue在定时函数中被赋予给value,然后通过get,将变化后的value给return出去
示例代码:
// 节流
export default function useThrottle(data, delay = 300) {
// 创建定时器
let timer = null;
return customRef((track, trigger) => {
return {
get() {
track() // 收集依赖
return value
},
set(newValue) {
// 清除定时器
if(timer != null){
clearTimeout(timer)
timer = null
}
// 创建定时器
timer = setTimeout(() => {
// 修改数据
data = value;
// 派发更新
trigger()
}, delay)
}
}
})
}
// 防抖
export default function useDebounce(value, delay = 200) {
let timeout = null
return customRef((track, trigger) => {
return {
get() {
track() // 收集依赖
return value
},
// newValue 值
set(newValue) {
// 清除定时器
if(timer != null){
clearTimeout(timer)
timer = null
}
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger() // 派发更新
}, delay)
}
}
})
}
使用:
<template>
<input type='text' v-model='keyword' />
</template>
<script setup>
import { useThrottle, useDebounce } from './'
const keyword = useDebounce(0, 1000)
</script>