在前端项目开发中,点击事件的防抖是一个永远无法错开的点,特别是针对一些复杂的业务场景,如果不做好防抖操作,就会导致页面或功能触发多次,引发异常或闪退。
在Flutter中可以通过扩展函数的特性 对Function增加全局扩展函数,实现防抖效果。
具体如下:
Dart
extension FunctionExt on Function {
VoidCallback throttle() {
return FunctionProxy(this).throttle;
}
// 立即执行目标操作,同时给出一个延迟的时间,
// 在该时间范围内如果再次触发了事件,该次事件会被忽略,直到超过该时间范围后触发事件才会被处理。
VoidCallback throttleWithTimeout({int? timeout}) {
return FunctionProxy(this, timeout: timeout).throttleWithTimeout;
}
// 在触发事件时,不立即执行目标操作,而是给出一个延迟的时间,
// 在该时间范围内如果再次触发了事件,则重置延迟时间,直到延迟时间结束才会执行目标操作。
VoidCallback debounce({int? timeout}) {
return FunctionProxy(this, timeout: timeout).debounce;
}
}
class FunctionProxy {
static final Map<String, bool> _funcThrottle = {};
static final Map<String, Timer> _funcDebounce = {};
final Function? target;
final int timeout;
FunctionProxy(this.target, {int? timeout}) : timeout = timeout ?? 500;
// 节流(默认延迟)
void throttle() async {
String key = hashCode.toString();
bool enable = _funcThrottle[key] ?? true;
if (enable) {
_funcThrottle[key] = false;
try {
await target?.call();
} catch (e) {
rethrow;
} finally {
_funcThrottle.remove(key);
}
}
}
// 节流(自定义延迟)
void throttleWithTimeout() {
String key = hashCode.toString();
bool enable = _funcThrottle[key] ?? true;
if (enable) {
_funcThrottle[key] = false;
Timer(Duration(milliseconds: timeout), () {
_funcThrottle.remove(key);
});
target?.call();
}
}
//延迟顺序执行的防抖
void debounce() {
String key = hashCode.toString();
Timer? timer = _funcDebounce[key];
timer?.cancel();
timer = Timer(Duration(milliseconds: timeout), () {
Timer? t = _funcDebounce.remove(key);
t?.cancel();
target?.call();
});
_funcDebounce[key] = timer;
}
}
在使用的地方
Dart
onBackPressed: () {
}.throttleWithTimeout(timeout: 500)
这种方案只是提供了一种防抖的实现,当然也可以自定义通用的Button,通过点击事件触发的时间自行判断处理。