节流和防抖函数的定义
- 防抖:只有在最后一次事件发生后的一定时间间隔内没有新的事件触发时,才执行相应的处理函数。
- 节流:在规定的时间间隔内最多只能执行一次相应的处理函数。
效果图
-
示例图
-
示例图运行结果如下:
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>JS防抖和节流函数</title>
<style>
* {
padding: 0;
margin: 0;
}
.container {
padding: 40px 16px 0;
box-sizing: border-box;
}
h2 {
text-align: center;
margin: 20px 0 40px;
}
p {
font-size: 15px;
line-height: 24px;
}
.keynote {
font-weight: 600;
color: #00bfc6;
}
.line {
padding: 10px 0;
box-sizing: border-box;
}
/* 通用样式,增加一些内边距和字体样式 */
input,
button {
padding: 10px 20px;
font-size: 16px;
font-family: Arial, sans-serif;
border: none;
/* 移除默认边框 */
outline: none;
/* 移除焦点时的轮廓线 */
cursor: pointer;
/* 鼠标悬停时显示手指形状,仅对button有效 */
}
#input {
border: 1px solid #bbb;
border-radius: 5px;
transition: border-color 0.3s;
margin-top: 40px;
}
#input:focus {
border-color: #00bfc6;
}
#btn {
background-color: #00bfc6;
color: white;
border-radius: 5px;
transition: background-color 0.3s;
height: 40px;
line-height: 40px;
padding-top: 0;
padding-bottom: 0;
}
#btn:hover {
background-color: #26e4eb;
}
</style>
</head>
<body>
<div class="container">
<h2>JS防抖和节流函数演示案例</h2>
<div class="desc">
<h3>1. 防抖</h3>
<P class="keynote">只有在最后一次事件发生后的一定时间间隔内没有新的事件触发时,才执行相应的处理函数。</P>
<p>例如:案例中的<b>输入框</b>,输入文字停止后一定时间之后才执行调接口的函数。</p>
<div class="line"></div>
<h3>1. 节流</h3>
<P class="keynote">在规定的时间间隔内最多只能执行一次相应的处理函数。</P>
<p>例如:案例中的<b>提交按钮</b>,1s内点击3次、4次,最后也只会触发一次提交的函数。</p>
</div>
<input id="input" type="text" placeholder="输入内容...">
<button id="btn">提交</button>
</div>
<script>
/**
* 防抖函数
* @param {Function} func 需要防抖的函数
* @param {number} wait 等待时间,单位毫秒
* @param {boolean} immediate 是否立即执行
* @return {Function} 返回防抖后的函数
*/
function debounce(func, wait, immediate = false) {
let timeout;
// 返回一个函数,这个函数会在一个时间间隔后执行
return function () {
const context = this;
const args = arguments;
// 如果已经设置了延时器,则清除它
if (timeout !== undefined) {
clearTimeout(timeout);
}
if (immediate && !timeout) {
// 如果设置为立即执行,并且没有延时器,则直接执行函数
func.apply(context, args);
}
// 否则,设置延时器,在指定时间后执行函数
timeout = setTimeout(() => {
timeout = undefined; // 清除延时器标识
if (!immediate) {
func.apply(context, args);
}
}, wait);
};
}
/**
* 节流函数
* @param {Function} func 需要节流的函数
* @param {number} wait 等待时间,单位为毫秒
* @returns {Function} 返回一个新的函数,这个函数会在一个时间间隔内最多执行一次func
*/
function throttle(func, wait) {
let lastRan = 0; // 上次执行时间
let timeout; // 定时器
return function () {
const context = this;
const args = arguments;
const now = Date.now();
// 如果当前时间与上次执行时间之差大于等待时间,或者还没有执行过
if (!lastRan || (now - lastRan >= wait)) {
// 清除之前的定时器(如果有的话)
if (timeout) clearTimeout(timeout);
// 执行函数
func.apply(context, args);
// 更新上次执行时间
lastRan = now;
} else if (!timeout) {
// 如果还没有设置定时器,则设置一个定时器在wait时间后执行
timeout = setTimeout(function () {
// 清除定时器引用
timeout = null;
}, wait - (now - lastRan));
}
};
}
</script>
<script>
// 防抖函数使用 - 开始
const input = document.getElementById('input')
const fn = debounce(getApi, 1000, false)
input.addEventListener('input', () => {
console.log('输入中');
fn()
})
function getApi() {
console.log('调用接口请求数据');
}
// 防抖函数使用 - 结束
// 节流函数使用 - 开始
const btn = document.getElementById('btn')
const fn1 = throttle(handleSubmit, 1000)
btn.addEventListener('click', () => {
console.log('点击按钮');
fn1()
})
function handleSubmit() {
console.log('提交');
}
// 节流函数使用 - 结束
</script>
</body>
</html>