概念
防抖:連續調用後等待一段時間執行一次,如果等待時間內又重新觸發,將重新等待一段時間執行
節流:連續調用,在指定時間段內內只執行一次
兩者的目的都是減少觸發的次數,保證性能和效率,區別在於業務場景和需求的不同。可以觸發防抖和節流的事件有:onscroll、onmouseMove、onChange、onResize等。
具體怎麼實現的還是看代碼比較容易理解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>防抖:多次調用後只執行一次</title>
</head>
<body style="height:1400px;">
<script>
'use strict'
function debounce(fn,delay){
var timer; //閉包保存局部變量
return function(...args) {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
fn(...args);
timer = null;
},delay);
}
}
//處理函數
function mouseMove (event) {
let e = event || window.event;
console.log('移動的位置了:',e.clientX,e.clientY);
}
window.onmousemove = debounce(mouseMove,1000);
</script>
</body>
</html>
react hooks裏的防抖
function useDebounce(fn, delay) {
const { current } = useRef(null);
//每次組件重新渲染,都會執行一遍所有的hooks,這樣debounce高階函數裏面的timer就不能起到緩存的作用
//因此需要將定時器綁定到對應的DOM上,防止其他hooks誤觸發
return function (...args) {
if (current.timer) {
clearTimeout(current.timer);
}
current.timer = setTimeout(fn.apply(this,...args), delay);
}
}
需要注意的地方:
1.用閉包保存上一次調用的函數
2.閉包裏需考慮this的指向和參數傳遞
3.執行完清除局部變量的引用,杜絕內存泄露
節流有兩種處理方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>節流:指定時間間隔只執行一次</title>
</head>
<body style="height:1400px;">
<script>
'use strict'
//第一種:用定時器去處理時間間隔
function throttle(fn,delay){
let valid = true;
return function() {
if(!valid){
return false;
}
valid = false;
setTimeout(() => {
fn();
valid = true;
}, delay);
}
}
function showTop () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滾動條位置:' + scrollTop);
}
window.onscroll = throttle(showTop,1000);
//第二種:用時間戳去處理時間間隔****************************************************************************************
function throttle1(fn,delay){
let startTime = new Date();//使用閉包,變量一直存在內存裏
return function() {
let endTime = new Date();
if(endTime - startTime >= delay){
fn();
startTime = endTime;
}
}
}
function mouseMove (event) {
let e = event || window.event;
console.log('移動的位置了:',e.clientX,e.clientY);
}
window.onmousemove = throttle1(mouseMove,1000)
</script>
</body>
</html>
react hooks裏面的節流
function useThrottle(fn, delay) {
const { current } = useRef(null);//用於防止其他hook導致的重新渲染
return function (...args) {
if (!current.timer) {
current.timer = setTimeout(() => {
delete current.timer;
}, delay);
fn(...args);
}
}
}