最近有個朋友在面試過程當中遇到一個問題:什麼是防抖
和節流
?糟了,這可觸碰到個人知識盲區了,好像聽也沒聽過這2個東西,痛定思痛,趕忙學習學習。javascript
在事件被觸發n秒以後執行,若是在此期間再次觸發事件,則從新開始計時。html
乍一看,這不是閒的蛋疼嗎?爲啥要等n秒以後再執行呢?vue
本着存在即合理的原則,咱看不懂但咱得去學啊!通過十秒鐘的思考,忽然想起來以前作過的公司的一個小程序,使用的mpvue
+
vant-weapp
,
van-field
標籤並無和數據進行雙向綁定,而是每次都要觸發
@input
事件,從而完成數據綁定:
這就致使了一個問題:
輸一個手機號要觸發11次事件!!若是是聯想搜索的話。。。那畫面太美!
咱們先本身想一下辦法來解決這個問題。java
phoneNumber
上而後進行聯想搜索,怎麼算輸入完成呢,輸入一個數字到找到下一個數字輸入大概須要1不到秒,只要用戶一秒內沒有再次輸入,則將輸入框內容與phoneNumber
綁定並進行聯想搜索(什麼?你說你輸入五個字符就停下?不怕後臺砍死你)debounce
、一個定時器、一個輸入框、一個判斷是否輸入完成的函數getPhone
getPhone
,輸入以後開啓1秒定時器,若是在1秒內再次進行了輸入,則清除以前的定時器,而且從新設置定時器;若是1秒內沒有輸入,則輸入結束觸發事件a
,進行聯想搜索。<input id="phone" type="text"/>
複製代碼
// 須要觸發的函數
function debounce(d){
console.log("聯想搜索phoneNumber:" + d)
}
let inp = document.querySelector("#phone");
// 輸入觸發的事件
function getPhone(fn,delay){
let timer;
// 使用閉包,保證每次使用的定時器是同一個
return (d)=>{
clearTimeout(timer);
timer = setTimeout(()=>{
fn(d);
// 結束以後清除定時器
clearTimeout(timer);
},delay)
}
}
let getPhoneDebounce = getPhone(debounce,1000);
inp.addEventListener('keyup',(e)=>{
getPhoneDebounce(e.target.value);
})
複製代碼
這時候看輸出:面試
是的只輸出了一次號碼,也就是說不用每次輸入都進行一次搜索了。若是持續觸發一個事件,則在必定的時間內只執行一次事件。小程序
那麼問題來了,既然是持續觸發了,那爲啥還要設定必定時間內只執行一次呢?廢話,你吃雞爲啥不用AKM非要去追夢搶狗雜呢?還不是由於AKM射速慢(狗雜真香)!閉包
咱們來試着作一個AKM的設計模擬:app
shot
, 一個判斷射擊間隔是否結束的函數nextShot
,一個觸發射擊的按鈕,判斷射擊是否結束的定時器timer
shot
,當繼續點擊的時候,射擊無效,只有過了定時器設置的時間才能夠繼續射擊。<button id="shot">射擊</button>
複製代碼
function shot(){
console.log('射擊')
}
let btn = document.querySelector('#shot');
function nextShot(fn,delay){
let timer;
// 閉包原理同上
return ()=>{
// 定時器存在,沒法射擊
if(timer){
console.log('禁止射擊');
}else{ // 定時器不存在,射擊,並設置定時器
fn();
timer = setTimeout(()=>{
// 定時器結束,能夠射擊
clearTimeout(timer);
timer = null;
},delay)
}
}
}
let start = nextShot(shot,20);
btn.addEventListener('click',()=>{
start();
})
複製代碼
當咱們瘋狂點擊按鈕的時候:函數
可能這個例子不是很突出,我再說個相似的,英雄聯盟和DNF的技能冷卻應該更適合~工具
公司的大數據組件目前是隻要頁面大小發生變化就會從新加載,這就致使了有時候拉一下控制檯會發生不少次請求,這個時候就能夠用防抖
來解決一下了~