故事背景:
項目有個需求是輸入框在輸入的時候進行搜索,展示下拉數據,但是沒必要輸入一個字都進行搜索,所以想到了在輸入結束200毫秒后再進行搜索,從而引出來了 js的節流(throttle),防抖(debounce),在網上想找個現成的用下,但是好多都不對,於是就自己搞了。
先看看概念
函數防抖(debounce):
在事件被觸發n秒后再執行回調,如果在這n秒內又被觸發,則重新計時;典型的案例就是輸入搜索:輸入結束后n秒才進行搜索請求,n秒內又輸入的內容,就重新計時。
函數節流(throttle):
規定在一個單位時間內,只能觸發一次函數,如果這個單位時間內觸發多次函數,只有一次生效; 典型的案例就是鼠標不斷點擊觸發,規定在n秒內多次點擊只有一次生效。
setTimeout內 this失效:
這是由於setTimeout函數調用的代碼運行在與所在函數完全分離的執行環境上,這會使得this指向的是window對象,看下圖 :
打了斷點,在Console下輸出 this 是Window對象,解決這個問題可以在setTimeout函數外面定義一個 that = this 就可以了,輸出 that果然就是該組件的對象
看在vue中的實際代碼:
1.輸入框,輸入最后一個字 2秒后執行(防抖:debounce):
html:
<input type="text" class="input" v-model="searchText" @keyup="debounce"/> js: debounce: function(){ let that = this if(timer){ clearTimeout(timer) } timer = setTimeout(function () { console.log('輸入') timer = undefined; },2000) }
timer 不要放在 debounce函數內部,要在文件全局定義,如下所示:
效果演示如下(輸入一次文字2秒后執行,多次輸入,還是執行一次,成功):
2.在2秒內多次點擊,只有一次生效(節流:throttle):
html: <div @click="throttle">點我。。</div> js: throttle: function(){ let that = this let now = +new Date(); if(lastTime && lastTime - now < 2000){ clearTimeout(timer) } timer = setTimeout(function () { console.log('點擊') lastTime = +new Date() },200) }
lastTime 跟 timer一樣,都要定義在文件的全局,如下:
效果圖如下:第一次點擊一下輸出一次,第二次雙擊選中,又輸出一次,成功。