|
@@ -218,32 +218,99 @@ function iterateOnFocusableNode(startNode, focusedNodeHandler) {
|
|
*
|
|
*
|
|
* fn: 需要被消抖的函数
|
|
* fn: 需要被消抖的函数
|
|
* delay: 消抖时长
|
|
* delay: 消抖时长
|
|
- * isImmediateCall: 是在第一次调用时立即执行fn,还是在最后一次调用后等delay时长再调用fn
|
|
|
|
|
|
+ * isImmediateCall: 是否在一组操作中的第一次调用时立即执行fn
|
|
|
|
+ * isRememberLastCall:是否在一组中最后一次调用后等delay时长再执行fn
|
|
*/
|
|
*/
|
|
-function debounce(fn, delay, isImmediateCall = false) {
|
|
|
|
|
|
+function debounce(fn, delay, isImmediateCall = false, isRememberLastCall = true) {
|
|
|
|
+ console.assert(isImmediateCall || isRememberLastCall, 'isImmediateCall 和 isRememberLastCall 至少应有一个是true,否则没有意义!')
|
|
let timer = null
|
|
let timer = null
|
|
// 上次调用的时刻
|
|
// 上次调用的时刻
|
|
let lastCallTime = 0
|
|
let lastCallTime = 0
|
|
|
|
|
|
- if (isImmediateCall) {
|
|
|
|
|
|
+ if (isImmediateCall && !isRememberLastCall) {
|
|
return function (...args) {
|
|
return function (...args) {
|
|
- const context = this
|
|
|
|
const currentTime = Date.now()
|
|
const currentTime = Date.now()
|
|
if (currentTime - lastCallTime >= delay) {
|
|
if (currentTime - lastCallTime >= delay) {
|
|
- fn.apply(context, args)
|
|
|
|
|
|
+ fn.apply(this, args)
|
|
}
|
|
}
|
|
lastCallTime = currentTime
|
|
lastCallTime = currentTime
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
|
|
+ } else if (!isImmediateCall && isRememberLastCall) {
|
|
return function (...args) {
|
|
return function (...args) {
|
|
if (timer) {
|
|
if (timer) {
|
|
clearTimeout(timer)
|
|
clearTimeout(timer)
|
|
}
|
|
}
|
|
- const context = this
|
|
|
|
timer = setTimeout(() => {
|
|
timer = setTimeout(() => {
|
|
- fn.apply(context, args)
|
|
|
|
|
|
+ fn.apply(this, args)
|
|
}, delay)
|
|
}, delay)
|
|
}
|
|
}
|
|
|
|
+ } else if (isImmediateCall && isRememberLastCall) {
|
|
|
|
+ return function (...args) {
|
|
|
|
+ const currentTime = Date.now()
|
|
|
|
+ if (currentTime - lastCallTime >= delay) { // 一组操作中的第一次
|
|
|
|
+ fn.apply(this, args)
|
|
|
|
+ lastCallTime = currentTime
|
|
|
|
+ return
|
|
|
|
+ } else { // 一组中的后续调用
|
|
|
|
+ if (timer) { // 在此之前存在中间调用
|
|
|
|
+ lastCallTime = currentTime
|
|
|
|
+ clearTimeout(timer)
|
|
|
|
+ }
|
|
|
|
+ timer = setTimeout(() => {
|
|
|
|
+ fn.apply(this, args)
|
|
|
|
+ lastCallTime = 0
|
|
|
|
+ timer = null
|
|
|
|
+ }, delay)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ console.error('不应该执行到这里!')
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class DebounceScheduler {
|
|
|
|
+ constructor(fn, delay, context, isImmediateCall = false) {
|
|
|
|
+ this.job = fn
|
|
|
|
+ this.delay = delay
|
|
|
|
+ this.context = context
|
|
|
|
+ this.timer = null
|
|
|
|
+ this.lastCallTime = 0
|
|
|
|
+ this.isImmediateCall = isImmediateCall
|
|
|
|
+ }
|
|
|
|
+ planToDo(...args) {
|
|
|
|
+ if (!this.isImmediateCall) {
|
|
|
|
+ if (this.timer) {
|
|
|
|
+ clearTimeout(this.timer)
|
|
|
|
+ this.timer = null
|
|
|
|
+ }
|
|
|
|
+ this.timer = setTimeout(() => {
|
|
|
|
+ this.job.apply(this.context, args)
|
|
|
|
+ }, this.delay)
|
|
|
|
+ } else {
|
|
|
|
+ const currentTime = Date.now()
|
|
|
|
+ if (currentTime - this.lastCallTime >= this.delay) { // 一组操作中的第一次
|
|
|
|
+ this.job.apply(this.context, args)
|
|
|
|
+ this.lastCallTime = currentTime
|
|
|
|
+ return
|
|
|
|
+ } else { // 一组中的后续调用
|
|
|
|
+ if (this.timer) { // 在此之前存在中间调用
|
|
|
|
+ this.lastCallTime = currentTime
|
|
|
|
+ clearTimeout(this.timer)
|
|
|
|
+ this.timer = null
|
|
|
|
+ }
|
|
|
|
+ this.timer = setTimeout(() => {
|
|
|
|
+ this.job.apply(this.context, args)
|
|
|
|
+ this.lastCallTime = 0
|
|
|
|
+ this.timer = null
|
|
|
|
+ }, this.delay)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ cancel() {
|
|
|
|
+ if (this.timer) {
|
|
|
|
+ clearTimeout(this.timer)
|
|
|
|
+ this.timer = null
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -251,7 +318,8 @@ export default {
|
|
mapTags,
|
|
mapTags,
|
|
extractTextForMagnify,
|
|
extractTextForMagnify,
|
|
isSameObject,
|
|
isSameObject,
|
|
|
|
+ getAndFocusNextNodeWithCustomAttribute,
|
|
iterateOnFocusableNode,
|
|
iterateOnFocusableNode,
|
|
debounce,
|
|
debounce,
|
|
- getAndFocusNextNodeWithCustomAttribute,
|
|
|
|
|
|
+ DebounceScheduler,
|
|
}
|
|
}
|