当滑动组件连续触发回调函数的三种解决办法
1. 节流(Throttle)
节流是一种限制函数调用频率的技术,它会在一定时间内只允许函数执行一次。在滑动组件中使用节流可以避免短时间内的连续触发。
@Entry
@Component
struct ThrottleSlideExample {
// 节流时间间隔,单位为毫秒
private throttleInterval: number = 500;
// 上次执行滑动处理的时间
private lastExecuteTime: number = 0;
build() {
Column({ space: 50 }) {
List({ space: 10 }) {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item) => {
ListItem() {
Text(`Item ${item}`)
.fontSize(20)
.padding(20)
.backgroundColor('#EEEEEE')
}
})
}
.onScroll((event: ScrollEvent) => {
const currentTime = Date.now();
if (currentTime - this.lastExecuteTime > this.throttleInterval) {
// 超过节流时间间隔,执行滑动处理
console.log('执行滑动处理');
this.lastExecuteTime = currentTime;
}
})
}
.width('100%')
}
}
代码解释:
throttleInterval
:定义节流的时间间隔,这里设置为 500 毫秒。lastExecuteTime
:记录上次执行滑动处理的时间。- 在
onScroll
事件中,获取当前时间currentTime
,判断当前时间与上次执行时间的差值是否超过节流时间间隔。如果超过,则执行滑动处理并更新lastExecuteTime
。
2. 防抖(Debounce)
防抖是指在一定时间内,如果函数被多次调用,只执行最后一次调用。在滑动组件中使用防抖可以避免连续触发带来的问题。
@Entry
@Component
struct DebounceSlideExample {
// 防抖时间间隔,单位为毫秒
private debounceInterval: number = 300;
// 定时器 ID
private timer: number | null = null;
build() {
Column({ space: 50 }) {
List({ space: 10 }) {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item) => {
ListItem() {
Text(`Item ${item}`)
.fontSize(20)
.padding(20)
.backgroundColor('#EEEEEE')
}
})
}
.onScroll((event: ScrollEvent) => {
if (this.timer) {
// 如果定时器存在,清除定时器
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
// 经过防抖时间间隔后执行滑动处理
console.log('执行滑动处理');
this.timer = null;
}, this.debounceInterval);
})
}
.width('100%')
}
}
代码解释:
debounceInterval
:定义防抖的时间间隔,这里设置为 300 毫秒。timer
:用于存储定时器的 ID。- 在
onScroll
事件中,如果定时器存在,则清除定时器。然后重新设置一个定时器,在经过防抖时间间隔后执行滑动处理。
3. 状态标记
使用状态标记来记录是否已经处理过一定次数的触发,当达到指定次数后,设置标记为已处理,直到满足特定条件(如一段时间后)再重置标记。
@Entry
@Component
struct FlagSlideExample {
// 记录滑动触发次数
private slideCount: number = 0;
// 允许的最大触发次数
private maxCount: number = 3;
// 处理标记
private isHandled: boolean = false;
build() {
Column({ space: 50 }) {
List({ space: 10 }) {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item) => {
ListItem() {
Text(`Item ${item}`)
.fontSize(20)
.padding(20)
.backgroundColor('#EEEEEE')
}
})
}
.onScroll((event: ScrollEvent) => {
if (!this.isHandled) {
this.slideCount++;
if (this.slideCount >= this.maxCount) {
// 达到最大触发次数,进行处理
console.log('执行滑动处理');
this.isHandled = true;
// 一段时间后重置标记
setTimeout(() => {
this.isHandled = false;
this.slideCount = 0;
}, 2000);
}
}
})
}
.width('100%')
}
}
代码解释:
slideCount
:记录滑动触发次数。maxCount
:允许的最大触发次数,这里设置为 3 次。isHandled
:处理标记,用于记录是否已经处理过最大触发次数。- 在
onScroll
事件中,如果标记为未处理,则增加触发次数。当达到最大触发次数时,执行滑动处理并设置标记为已处理。然后使用setTimeout
在 2000 毫秒(即 2 秒)后重置标记和触发次数。
这些方法各有优缺点,你可以根据具体的业务需求选择合适的方法来处理滑动组件连续触发的问题。