本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
【若川视野 x 源码共读】第25期 | 跟着underscore学防抖点击了解本期详情一起参与。
1. 描述
简单看一下事件重复触发的场景。
index.html
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container{
width: 100%;
height: 200px;
line-height: 200px;
text-align: center;
color: #fff;
background-color: #444;
font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="./debounce.js"></script>
</body>
</html>
debounce.js
let count = 1
let container = document.querySelector('#container')
function getUserAction() {
container.innerHTML = count++
return 22
}
container.onmousemove = getUserAction
看一下效果,从左到右执行了 384 次。
如何防止被重复触发,解决方案有两种:
- debounce 防抖
- throttle 节流
2.防抖
2.1 满足基本防抖要求
适配了 this 指针,参数基本功能。
function debounce(func, awaitTime = 1000) {
let timeoutId = void 0
return function() {
let that = this
let thatArg = arguments
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
func.apply(that, thatArg)
}, awaitTime)
}
}
container.onmousemove = debounce(getUserAction, 1000)
项目中,有时候是需要立即执行。
2.2 增加立即执行可选配置
function debounce(func, awaitTime = 1000, immediate = true) {
let timeoutId = void 0
return function() {
let that = this
let thatArg = arguments
clearTimeout(timeoutId)
if (immediate) {
let callNow = !timeoutId
timeoutId = setTimeout(() => {
timeoutId = void 0
}, awaitTime)
if (callNow) {
func.apply(that, thatArg)
}
} else {
timeoutId = setTimeout(() => {
func.apply(that, thatArg)
}, awaitTime)
}
}
}
container.onmousemove = debounce(getUserAction, 1000)
3. 总结
项目中对于经常触发的事件,比如 change , keyup , keydown 还是很有必要防抖的,而本文的防抖代码适用场景也是针对事件重复触发的情况。
本次主要是研究防抖,节流会写在下一篇。