在介绍防抖节流之前,先了解一下定时器和延时器:
1.定时器:setInterval(()+>{},time),定一段时间time,并间隔time重复执行()=>{}
2.延时器:setTimeout(()=>{},time),定一段时间time,time时间过后执行一次()=>{}
1 防抖 Debounce
介绍
当一个事件持续触发时,防抖会等待一段时间,在这段时间之内,事件没有再触发,执行最后一次触发的操作。
场景
在处理搜索框的输入事件,为避免每次输入都发送请求,在等待用户输入完毕后再发送请求。
示例
由于输入框发生变化时,onChange()事件就会执行,可以看到,每当输入框里有输入或者删除,立即有日志打印,相当于用户只要在搜索框输入内容,页面就会向服务器发起请求,这样很浪费服务器资源。
此时,加入if...语句,可以理解为,防抖 => 防止每次输入内容,都立马执行延时器中的输出日志,而是输入内容停止1s后输出日志。
防抖输入框源码:
@Entry
@Component
struct Index {
@State tid: number = -1
build() {
Column() {
TextInput()
//输入内容发生变化时,触发onChange()事件
.onChange(value => {
if (this.tid != -1) {
//清除上一次输入操作创建的延时器
clearTimeout(this.tid)
}
this.tid = setTimeout(() => {
console.log("输入的内容:", value, "延时器id:", this.tid)
}, 1000)
})
}
}
}
封装防抖函数
需求:防抖函数,参数:传入业务逻辑和时间间隔,返回值:返回一个添加了防抖处理的函数。
完整代码
//封装防抖函数
const debounce = (func: (value: string) => void, time: number) => {
let tid = -1
const newFunc = (value: string) => {
if (tid != -1) {
clearTimeout(tid)
}
tid = setTimeout(() => {
func(value)
}, time)
}
return newFunc
}
@Entry
@Component
struct Index {
onTextChange = debounce((text) => {
console.log("输入的内容:", text)
}, 1000)
build() {
Column() {
TextInput()
.backgroundColor("#ffe0dede")
.onChange(value => {
this.onTextChange(value)
})
}
}
}
2 节流 Throttle
介绍
控制在一定的时间间隔内只执行第一次函数(业务),来限制事件的触发次数。
场景
处理滚动事件,限制频繁触发的情况,例如在滚动加载场景中,只有在用户停止滚动一段时间后才加载内容。(用户在第一次滚动触底后,等待一段时间获取到内容,在等待的这段时间内,多次滑动,并不会触发多次请求数据的业务,只有第一次的请求有效。)
示例
滑动触底后,即触发onReachEnd()事件,第一次触底后,延迟3s获取到数据,频繁滑动,在3s之内可以多次请求数据。
加入节流逻辑之后,触底后,在3s内多次滑动到触底,最终只获取到一次数据。
节流获取数据源码:
@Entry
@Component
struct Index {
@State list: number[] = Array.from({ length: 10 }, (val: undefined, index: number) => index)
@State isRun: boolean = false
addList = () => {
const newList: number[] = Array.from({ length: 10 }, (val: undefined, index: number) => index)
this.list.push(...newList)
}
build() {
Column() {
List() {
ForEach(this.list, (item: number) => {
ListItem() {
Text(item.toString())
.padding(20)
}
.height(50)
})
}
.width("100%")
.height(300)
.divider({ strokeWidth: 1, color: Color.Red })
.onReachEnd(() => {
if (this.isRun) {
return //直接返回:不执行后续代码,立即结束当前函数或块的执行
}
this.isRun = true
setTimeout(() => {
this.addList()
console.log("获取数据")
//业务做完了
this.isRun = false
}, 3000)
})
}
}
}
封装节流函数
需求:节流函数,参数:传入业务逻辑和时间间隔,返回值:返回一个添加了节流处理的函数。
//封装节流函数
const throttle = (func: () => void, time: number) => {
let isRun: boolean = false
const newFunc = () => {
if (isRun) {
return
}
isRun = true
setTimeout(() => {
func()
isRun = false
}, time)
}
return newFunc
}
@Entry
@Component
struct Index {
@State list: number[] = Array.from({ length: 10 }, (val: undefined, index: number) => index)
addList = () => {
const newList: number[] = Array.from({ length: 10 }, (val: undefined, index: number) => index)
this.list.push(...newList)
}
getData = throttle(() => {
this.addList()
console.log("获取数据")
}, 3000)
build() {
Column() {
List() {
ForEach(this.list, (item: number) => {
ListItem() {
Text(item.toString())
.padding(20)
}
.height(50)
})
}
.width("100%")
.height(300)
.divider({ strokeWidth: 1, color: Color.Red })
.onReachEnd(() => {
this.getData()
})
}
}
}
更多关于防抖、节流介绍、应用场景可移步https://zhuanlan.zhihu.com/p/655620823