防抖
在小程序上使用之前得先介绍一下防抖。无非就是将一个频繁的操作延迟触发并且同时减少触发次数。
本质就是利用闭包保存定时器数据,并且在延迟时间内频繁触发会清除上一次的定时器操作。最后能触发的只能是触发事件之后的延迟时间内不再进行触发事件,则该在延迟时间结束后事件执行。(假设定时器设置的延迟时间为 500ms,第一次触发事件,第二次触发事件和第一次的时间间隔小于500ms,则清除第一次事件的触发,第三次触发事件和第二次的时间间隔若小于 500ms,则第二次不执行,… 直到第N次触发事件后的 500ms 不进行事件的触发,则第N次事件执行)
/**
* 防抖函数
* @param {Function} fn 需要进行防抖的函数引用
* @param {Number} wait 延迟时间
*/
function debounce(fn, wait) {
let timer; // 关键
return function () { // 最终交由输入框执行的是这个返回函数,而不是debounce(fn,wait),关键
clearTimeout(timer); // 清除上一次的定时器
timer = setTimeout(() => { // 设置新的定时器
fn.apply(this, arguments) // 执行需要执行的防抖函数(例如输入事件)
}, wait); // 设置延迟时间
}
}
微信小程序输入事件防抖
注:本次例子是在小程序中封装的输入框组件,请结合自己需求进行相应灵活更改。
输入框组件的 data 对象
/**
* 组件的初始数据
*/
data: {
// 延迟时间毫秒
delay: 500,
// 执行防抖函数的返回函数引用
delayFun: null,
},
- 首先必须有一个防抖函数(这是废话),可用上面的防抖方法。
/**
* 防抖
*/
debounce(fn, delay) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
},
- 触发父组件的事件(仅在自己封装的输入框组件内可使用)
/**
* 向父组件触发 input 事件,可携带参数
* @param {String} eventName 事件名称
* @param {Any} value 传递的参数
*/
triggerEventToFather(eventName, value) {
this.triggerEvent(eventName, value);
}
- 执行防抖函数以获取防抖函数中的返回函数。
这个关键,因为输入框输入事件进行防抖的是 debounce(fn,delay) 这个函数中的 return 出来的返回函数。
// 执行防抖函数
handleDebounceFn(debounceFn, ...arg) {
return debounceFn(arg[0], arg[1]);
},
- 在组件的生命周期钩子中实现防抖函数以获取返回函数
lifetimes: {
// 组件创建完成
attached: function () {
// 执行防抖函数,返回函数(防抖函数的返回函数)
// 注:this.handleDebounceFn(第一个参数是防抖函数,第二个参数是需要进行防抖的方法这里指的是触发父组件的函数,第三个参数是延迟时间) 返回的是防抖函数执行后的返回函数,最后保存函数引用交由输入框的输入事件执行,则整个输入防抖完成。
let delayFun = this.handleDebounceFn(this.debounce, (eventName, value) => {
this.triggerEventToFather(eventName, value)
}, this.data.delay);
// 将this.handleDebounceFn 函数的返回的函数引用保存到 data 中。
this.setData({
delayFun
})
},
},
- 输入框的输入事件
// 输入框的事件
handleInput(e) {
// 防抖-输入
// 执行 data 中的 delayFun 函数
this.data.delayFun("search-input", e.detail.value);
},
- 在父组件中触发 search-input 事件即可。