防抖原理:不管你调用多少次,我只在固定时间范围内执行一次 应用场景: 按钮点击事件,屏幕滚动事件, 鼠标滚动事件等等
**先来一个简陋版本**
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>
#content {
text-align: center;
font-size: 30px;
}
</style>
</head>
<body>
<div id="content"></div>
</body>
<script src="./debounce"></script>
</html>
然后就是debounce.js部分
var count = 1;
var contentBox = document.getElementById('content');
function getUserAction() {
contentBox.innerHTML = count++
}
function debounce(fn, wait) {
let timeout
return function () {
clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
content.onmousemove = debounce(getUserAction, 300);
注意: 此时你会发现,使用了 debounce 之后getUserAction 的 this 指向由
变成了 window, 所以我们需要通过 apply 方法改变 this 指向**再来一个进阶版本**
var count = 1;
var contentBox = document.getElementById('content');
function getUserAction() {
contentBox.innerHTML = count++
}
function debounce(fn, wait) {
var timeOut
return function () {
let context = this
let args = arguments
clearTimeout(timeOut)
timeOut = setTimeout(function () {
fn.apply(context, args)
}, wait)
}
}
content.onmousemove = debounce(getUserAction, 300);
当做到这里,基本使用已经没有什么问题了,但是是否可以再优化呢,比如,我想先执行一次,然后再n秒后再执行
var count = 1;
var contentBox = document.getElementById('content');
function getUserAction() {
contentBox.innerHTML = count++
}
function debounce(fn, wait, Immediately) {
var timeOut
return function () {
let context = this
let args = arguments
if (timeOut) clearTimeout(timeout);
if (Immediately) {
var currentCall = !timeOut
timeOut = setTimeout(function () {
timeOut = null
}, wait)
if (currentCall) func.apply(context, args)
} else {
timeOut = setTimeout(function () {
fn.apply(context, args)
}, wait)
}
}
}
content.onmousemove = debounce(getUserAction, 300);