事件優化
防抖與節流
防抖:
所謂防抖,就是把觸發非常頻繁的事件合並成一次去執行。即在指定時間內只執行一次回調函數,如果在指定的時間內又觸發了該事件,則回調函數的執行時間會基於此刻重新開始計算。
指觸發事件后在n秒內只執行一次,若在n秒內再次觸發則重新計算
節流:
所謂節流,是指頻繁觸發事件時,只會在指定的事件段內執行事件回調,即觸發事件間隔大於等於指定的事件才會執行回調函數。
連續發生的事件在n秒內只執行一次函數
為什么要防抖或節流
- 及時查詢時,減少服務器壓力。
- 頻繁執行DOM操作、資源加載等重行為,導致UI停頓甚至瀏覽器崩潰
需求是以一定的頻率執行后續的處理。
實現
防抖
只要觸發,就會清除上一個計時器,又注冊新的一個計時器。直到停止觸發wait時間后,才會執行回調函數。
不斷觸發事件,就會不斷重復這個過程,達到防止目標函數過於頻繁的調用的目的。
function debounce(func, wait) {
let timeout;
return function () {
if (timeout) window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
func.apply(this, arguments);
}, wait);
};
}
調用apply改變傳入的func方法中的this指向,指向綁定事件的DOM元素。
節流
只要觸發,只會在當前計時器為空時,注冊計時器。
不斷觸發事件,只會在固定的事件間隔觸發。
setTimeout
function throttle(func, wait) {
let timeout;
return function () {
if (!timeout) {
timeout = window.setTimeout(function () {
func.apply(this, arguments);
timeout = null;
}, wait);
}
};
}
時間戳
function throttleTime(func, wait) {
let prev = 0;
return function () {
let now = Date.now();
if (now - prev > wait) {
func.apply(this);
prev = now;
}
};
}
所有
<!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>
<button id="bt1">防抖</button>
<button id="bt2">節流</button>
</body>
<script>
// 防抖
function debounce(func, wait) {
let timeout;
return function () {
if (timeout) window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
func.apply(this, arguments);
}, wait);
};
}
// 節流
function throttle(func, wait) {
let timeout;
return function () {
if (!timeout) {
timeout = window.setTimeout(function () {
func.apply(this, arguments);
timeout = null;
}, wait);
}
};
}
function throttleTime(func, wait) {
let prev = 0;
return function () {
let now = Date.now();
if (now - prev > wait) {
func.apply(this);
prev = now;
}
};
}
let bt1 = document.getElementById("bt1");
let bt2 = document.getElementById("bt2");
bt1.onclick = debounce(function () {
console.log(1);
}, 1000);
bt2.onclick = throttleTime(function () {
console.log(2);
}, 1000);
</script>
</html>