在一個電影項目中,我想在電影的列表中,保存下拉的當前位置,防止你切換頁面後,再切換回當前的電影列表頁,他就又回到電影的第一條數據。
這時候,我不想每次只要滑動一點,就保存當前位置,我想隔一段時間,保存一次,這時候,就能夠使用防抖和節流。git
說白了,防抖節流就是使用定時器來實現咱們的目的。bash
關於定時器的用法,請移步:JS中經常使用計時器的用法session
防抖(debounce):app
在事件被觸發n秒後再執行回調,若是在這n秒內又被觸發,則從新計時。函數
典型的案例就是輸入框搜索:輸入結束後n秒才進行搜索請求,n秒內又輸入的內容,則從新計時。post
節流(throttle):ui
規定在一個單位時間內,只能觸發一次函數,若是這個單位時間內觸發屢次函數,只有一次生效。this
典型的案例就是鼠標不斷點擊觸發,規定在n秒內屢次點擊只生效一次。spa
下拉列表,隔一段時間保存當前下拉位置。code
咱們能夠在mounted
鉤子中實現咱們的防抖:
// 防抖 定時器
let timer;
//list就是電影列表 ref="list" $el獲取DOM元素
this.$refs.list.$el.addEventListener("scroll", e => {
console.log("---->",e.target.scrollTop) //不使用防抖
if (timer) {
//清空timer
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log(e.target.scrollTop) //使用防抖
//在sessionStorage中保存當前下拉位置
// sessionStorage.setItem("position", e.target.scrollTop);
}, 75); //75ms爲最佳
});
複製代碼
效果演示(隔一段時間保存當前位置):
加---->
爲不使用防抖,沒加的則使用防抖
輸入框搜索隔段時間進行搜索請求:
<template>
<div>
<input type="text" @keyup="debounce" />
</div>
</template>
<script>
//定義 timer
let timer;
export default {
methods: {
debounce: function() {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log("防抖...");
timer = undefined;
}, 2000);
}
}
};
</script>
複製代碼
在n秒內點擊屢次,只有一次生效。
<template>
<div>
<button @click="throttle">按鈕</button>
</div>
</template>
<script>
//定義
let timer, lastTime;
let now = +new Date();
export default {
methods: {
throttle: function() {
if (lastTime && now - lastTime < 200) {
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log("點擊...");
lastTime = +new Date();
}, 200);
}
}
};
</script>
複製代碼
效果演示:
固然,也能夠對這兩個方法進行封裝,以便在多處使用。
/**
* 函數防抖 (只執行最後一次點擊)
*/
export const Debounce = (fn, t) => {
let delay = t || 500;
let timer;
return function () {
let args = arguments;
if(timer){
clearTimeout(timer);
}
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, delay);
}
};
/*
* 函數節流
*/
export const Throttle = (fn, t) => {
let last;
let timer;
let interval = t || 500;
return function () {
let args = arguments;
let now = +new Date();
if (last && now - last < interval) {
clearTimeout(timer);
timer = setTimeout(() => {
last = now;
fn.apply(this, args);
}, interval);
} else {
last = now;
fn.apply(this, args);
}
}
};
複製代碼