防抖和節流
瀏覽器的 resize、scroll、keypress、mousemove 等事件在觸發時,會不斷地呼叫系結在事件上的回呼函式,極大地浪費資源,降低前端性能,為了優化體驗,需要對這類事件進行呼叫次數的限制,
- 狂點一個按鈕
- 頁面滾動
- 入模糊匹配
- ,,,,,,
防抖(debounce)
在某一次高頻觸發下,我們只識別一次(可以控制開始觸發,還是最后一次觸發)
詳細:假設我們規定500MS觸發多次算是高頻,只要我們檢測到是高頻觸發了,則在本次頻繁操作下(哪怕你操作了10次)也是只觸發一次…
<button id="submit">點擊</button>
function () {
console.log("hello world")
}
上面按鈕每一次點擊,都會觸發列印,如果瘋狂點擊,那么下面就會瘋狂列印,會降低性能,
實際開發1:使用按鈕只會,移除事件系結
<button id="submit">點擊</button>
function handle() {
submit.onclick = null;
submit.disabled = true;
console.log('OK');
setTimeout(() => {
submit.onclick = handle;
submit.disabled = false;
}, 1000);
}
submit.onclick = handle;
實際開發2:使用按鈕只會,移除事件系結
<button id="submit">點擊</button>
let flag = false;
submit.onclick = function () {
if (flag) return;
flag = true;
console.log('OK');
setTimeout(() => {
// 事情處理完
flag = false;
}, 1000);
};
封裝一個函式防抖的方法
<button id="submit">點擊</button>
function debounce(func, wait, immediate) {
// 多個引數及傳遞默認的處理
if (typeof func !== "function") throw new TypeError("func must be an function!");
if (typeof wait === "undefined") wait = 500;
if (typeof wait === "boolean") {
immediate = wait;
wait = 500;
}
if (typeof immediate !== "boolean") immediate = false;
// 設定定時器回傳值標識
let timer = null;
return function proxy(...params) {
let self = this,
now = immediate && !timer;
clearTimeout(timer);
timer = setTimeout(function () {
timer = null;
!immediate ? func.call(self, ...params) : null;
}, wait);
// 第一次觸發就立即執行
now ? func.call(self, ...params) : null;
};
}
function handle(ev) {
// 具體在點擊的時候要處理的業務
console.log('OK', this, ev);
}
submit.onclick = debounce(handle, true);
// submit.onclick = proxy; 瘋狂點擊的情況下,proxy會被瘋狂執行,我們需要在proxy中根據頻率管控handle的執行次數
// submit.onclick = handle; //handle->this:submit 傳遞一個事件物件
簡潔版本的防抖
function myDebounce(fn, interval = 500) {
let timeout = null;
return function () {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, interval);
};
}
function doSomething(){
// onm ousemove觸發的事件回呼函式
}
container.onmousemove = myDebounce(doSomething, 300);
節流(throttle)
在某一次高頻觸發下,我們不是只識別一次,按照我們設定的間隔時間(自己規定的頻率),沒到達這個頻率都會觸發一次
詳細:假設我們規定頻率是500MS,我們操作了10min,觸發的次數=(10601000)/500
比如,滾動頁面,觸發了多次列印
body {
height: 3000px;
overflow-x: hidden;
background: -webkit-linear-gradient(top left, lightblue, pink, orange);
}
window.onscroll = function () {
// 默認情況下,頁面滾動中:瀏覽器在最快的反應時間內(4~6MS),就會識別監聽一次事件觸發,把系結的方法執行,這樣導致方法執行的次數過多,造成不必要的資源浪費
console.log('OK');
};
封裝一個函式節流的方法
body {
height: 3000px;
overflow-x: hidden;
background: -webkit-linear-gradient(top left, lightblue, pink, orange);
}
function throttle(func, wait) {
if (typeof func !== "function") throw new TypeError("func must be an function!");
if (typeof wait === "undefined") wait = 500;
let timer = null,
previous = 0; //記錄上一次操作的時間
return function proxy(...params) {
let self = this,
now = new Date(), //當前這次觸發操作的時間
remaining = wait - (now - previous);
if (remaining <= 0) {
// 兩次間隔時間超過wait了,直接執行即可
clearTimeout(timer);
timer = null;
previous = now;
func.call(self, ...params);
} else if (!timer) {
// 兩次觸發的間隔時間沒有超過wait,則設定定時器,讓其等待remaining這么久之后執行一次「前提:沒有設定過定時器」
timer = setTimeout(function () {
clearTimeout(timer);
timer = null;
previous = new Date();
func.call(self, ...params);
}, remaining);
}
};
}
function handle() {
console.log('OK');
}
window.onscroll = throttle(handle, 500);
簡潔版本的節流
function myThrottle(fn, interval = 500) {
let run = true;
return function () {
if (!run) return;
run = false;
setTimeout(() => {
fn.apply(this, arguments);
run = true;
}, interval);
};
}
function doSomething(){
// onm ousemove觸發的事件回呼函式
}
container.onmousemove = myThrottle(doSomething, 300);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/241356.html
標籤:其他
上一篇:Vant修改主體顏色樣式
下一篇:手摸手帶你學CSS
