节流、防抖
节流和防抖的理解
- 节流:当一个事件持续触发时,我们期望降低事件触发的频率,事件处理函数还是会触发多次。比如在移动端手机浏览器对
onscroll
事件不能实时触发,就是在内部做了节流处理。 - 防抖:当一个事件持续触发时,我们期望在最后一次事件触发时再执行事件处理函数。
- 使用场景:
- 在连续触发事件的场景中,仅仅需要在最后一次事件触发时执行事件处理函数,使用
防抖
。比如根据输入框内容进行搜索查询、浏览器窗口resize后重新渲染页面等。 - 在连续触发事件的场景中,需要降低事件触发的频次,使用
节流
。如上拉加载更多数据、图片懒加载(监听图片元素是否快到可视区域了)等
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>节流2</title>
</head>
<body>
<button id="btn1">按钮1 点击触发</button>
<br />
<button id="btn2">点击该按钮,触发10次按钮1的点击</button>
<script>
const btn1 = document.getElementById('btn1')
const btn2 = document.getElementById('btn2')
btn1.addEventListener('click', throttle(handler, 301), false)
btn2.addEventListener(
'click',
async function () {
for (let i = 1; i < 11; i++) {
await delay(100)
const event = new CustomEvent('click', { detail: i })
btn1.dispatchEvent(event)
}
},
false
)
function delay(ts) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ts)
})
}
function handler(ev) {
console.log('按钮被点击了', ev)
}
function throttle(fn, delay) {
let timer = null
return function (ev) {
if (timer) return
timer = setTimeout(() => {
fn(ev)
timer = null
}, delay)
}
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" value="" id="ipt1" />
<button id="btn1">按钮1</button>
<br />
<script>
let btn1 = document.getElementById('btn1')
btn1.addEventListener('click', debounce(handler, 1000), false)
function handler() {
console.log('按钮1被点击了 执行对应的业务逻辑')
}
function debounce(fn, delay) {
let timer = null
return function () {
clearTimeout(timer)
timer = setTimeout(() => {
fn()
}, delay)
}
}
function sum(a, b) {
return a + b
}
sum(1, 2)
sum(2, 3)
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input type="text" value="" id="ipt1" />
<button id="btn1">按钮1</button>
<br />
<button id="btn2">按钮2 点击该按钮触发10次按钮1的点击</button>
<script>
let btn1 = document.getElementById('btn1')
let btn2 = document.getElementById('btn2')
btn1.addEventListener('click', debounce(handler, 1000), false)
function handler(ev) {
console.log('按钮1被点击了 执行对应的业务逻辑', ev)
}
function debounce(fn, delay) {
let timer = null
return function (ev) {
clearTimeout(timer)
timer = setTimeout(() => {
fn(ev)
}, delay)
}
}
btn2.addEventListener(
'click',
async function () {
for (let i = 1; i < 11; i++) {
await delay(100)
const event = new CustomEvent('click', { detail: i })
btn1.dispatchEvent(event)
}
},
false
)
function delay(ts) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, ts)
})
}
function sum(a, b) {
return a + b
}
sum(1, 2)
sum(2, 3)
</script>
</body>
</html>