一:介绍
防抖函数原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
防抖动和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行
eg. 像仿百度搜索,就应该用防抖,当我连续不断输入时,不会发送请求;当我一段时间内不输入了,才会发送一次请求;如果小于这段时间继续输入的话,时间会重新计算,也不会发送请求。
手写简化版:
// func是用户传入需要防抖的函数
// wait是等待时间
const debounce = (func, wait = 50) => {
// 缓存一个定时器id
let timer = 0
// 这里返回的函数是每次用户实际调用的防抖函数
// 如果已经设定过定时器了就清空上一次的定时器
// 开始一个新的定时器,延迟执行用户传入的方法
return function(...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, wait)
}
}
适用场景:
按钮提交场景:防止多次提交按钮,只执行最后提交的一次 服务端验证场景:表单验证需要服务端配合,只执行一段连续的输入事件的最后一次,还有搜索联想词功能类似
二:层解释
在理解防抖之前,先来了解下出现抖动的场景:
- 开发搜索功能的时候,输入字符执行查询操作,network 中会瞬间出现无数的ajax请求
- 进行页面适配,调整窗口大小的时候适配不同的布局,如果适配业务复杂,浏览器可能出现卡顿现象
抖动:频繁触发而导致不可预测后果的现象。
防抖:防止在短时间内频繁触发,一段时间内只触发一次。
我们常常遇到的一些频繁触发的事件有:
- 输入框的 keyup / keydown
- 调整窗口大小的 resize
- 页面滚动的 scroll
- 鼠标滑动的 mousedown / mousemove
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>debounce</title>
</head>
<body>
<div>
<input id="search" type="text" />
<div id="result"></div>
<!-- <script>
let count = 0;
debugger
let result = document.getElementById("result");
let search = document.getElementById("search");
search.addEventListener("keyup", onSearch);
function onSearch() {
console.log(this);
result.innerHTML = count++;
// TODO: 发送ajax请求
}
</script>-->
<!-- 防抖处理-->
<!--<script>
function debounce(func,wait = 1000){
let timeout;
return function () {
clearTimeout(timeout)
timeout = setTimeout(func,wait)
}
}
let count = 0;
let result = document.getElementById("result");
let search = document.getElementById("search");
search.addEventListener("keyup", debounce(onSearch,1000));
function onSearch() {
console.log(this);
result.innerHTML = count++;
// TODO: 发送ajax请求
}
</script>-->
<!-- 解决this指向问题-->
<script>
function debounce(func,wait = 1000){
let timeout;
return function () {
let that= this
let args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function () {
func.apply(that,args);
},wait);
}
}
let count = 0;
let result = document.getElementById("result");
let search = document.getElementById("search");
search.addEventListener("keyup", debounce(onSearch,1000));
function onSearch() {
console.log(this);
result.innerHTML = count++;
// TODO: 发送ajax请求
}
</script>
</div>
</body>
</html>