debounce【去抖】
描述
防抖函数
# 1.示例
import { debounce } from 'sf-utils2'
const resizeFn = e => {
console.log('滚动了', e.target)
}
// 在计时结束之后执行
const debounceResize = debounce(resizeFn, 400) // 距离上次执行间隔时间400ms,以最后一次运行为基准
window.addEventListener('resize', debounceResize, false) // 开始监听
window.removeEventListener('resize', debounceResize, false) // 卸载监听
// 在计时结束之前执行
window.addEventListener(
'resize',
debounce(resizeFn, 300, {
leading: true,
trailing: false
})
)
// 在计时结束之后执行
window.addEventListener(
'resize',
debounce(resizeFn, 300, {
leading: false,
trailing: true
})
)
let func = debounce(function (msg) {
console.log(msg)
}, 300)
func('执行一次')
func.cancel()
func('取消后中断计时,再次调用会马上执行')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 2.入参说明
| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
|---|---|---|---|---|
| fn | 回调函数 | Function | 是 | |
| wait | 距离上次执行间隔时间,单位毫秒 | Number | 否 | 默认 800 毫秒 |
| options | 选项 详情见下 👇 | Object | 否 |
# options 对象
| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
|---|---|---|---|---|
| leading | 是否在之前执行 | Boolean | 否 | false |
| trailing | 是否在之后执行 | Boolean | 否 | true |
# 3.源码
/**
* 防抖函数,函数去抖;当被调用 n 毫秒后才会执行,如果在这时间内又被调用则将重新计算执行时间
*
* @param {Function} callback 回调
* @param {Number} wait 多少秒毫 默认值是300毫秒
* @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
* @return {Function}
*/
function debounce(callback, wait = 300, options = { leading: false, trailing: true }) {
let args, context
let opts = options || {}
let runFlag = false
let isDestroy = false
let timeout = 0
let isLeading = typeof options === 'boolean'
let optLeading = 'leading' in opts ? opts.leading : isLeading
let optTrailing = 'trailing' in opts ? opts.trailing : !isLeading
let runFn = function () {
if (!isDestroy) {
runFlag = true
timeout = 0
callback.apply(context, args)
}
}
let endFn = function () {
if (optLeading === true) {
timeout = 0
}
if (!isDestroy && !runFlag && optTrailing === true) {
runFn()
}
}
let cancelFn = function () {
let rest = timeout !== 0
clearTimeout(timeout)
args = null
context = null
timeout = 0
return rest
}
let debounced = function () {
runFlag = false
args = arguments
context = this
if (timeout === 0) {
if (optLeading === true) {
runFn()
}
} else {
clearTimeout(timeout)
}
timeout = setTimeout(endFn, wait)
}
debounced.cancel = cancelFn
return debounced
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
上次更新: 2023/06/24, 19:35:48