vue中的正確使用方式

1.png
在這個地方相信好多人的使用方式,會直接定義函數(shù),然后在函數(shù)中使用debounce的 ,這樣的使用方法是錯誤的

2.png
為啥呢?這個和vue的事件綁定原理有關(guān),這里不詳細(xì)介紹。如果直接在函數(shù)體內(nèi)部使用的話,最后的結(jié)果是,一個匿名的立即執(zhí)行函數(shù)來進行執(zhí)行,這樣是不對的
原理
函數(shù)的防抖
函數(shù)的防抖是在多少時間后再來執(zhí)行函數(shù),我們可以理解為這樣的一種生活場景(坐升降電梯),
在點擊電梯的開門按鈕后,電梯會開門,然后等待一段時間來關(guān)門。但是如果在等待的期間,
有人再次點擊開門按鈕,那么電梯后繼續(xù)等待關(guān)門時間,直到等待關(guān)門時間結(jié)束,沒有人來
點擊開門按鈕后,電梯才會開始工作。
第一次非立即執(zhí)行
export function debounce(f, t){
let timer;
return (...arg) => {
clearTimeout(timer);
timer = setTimeout(() =>{
f( ...arg)
}, t)
}
}

20210516221519342.gif
第一次立即執(zhí)行
對于有些場景來說,第一次我不需要等待,需要立即執(zhí)行,例如:打開控制臺獲取窗口試圖大小
(這里我們需要一直改變窗口的大小,等停下來再次獲取窗口視圖大?。?
export function debounceFirstExe(f, t){
let timer, flag = true;
return (...args) => {
if (flag){
f(...args);
flag = false;
}else {
clearTimeout(timer);
timer = setTimeout(() => {
f(...args);
flag = true;
}, t)
}
}
}

35.gif
export function debounce(f, t,im = false){
let timer, flag = true;
return (...args) => {
// 需要立即執(zhí)行的情況
if (im){
if (flag){
f(...args);
flag = false;
}else {
clearTimeout(timer);
timer = setTimeout(() => {
f(...args);
flag = true
}, t)
}
}else {
// 非立即執(zhí)行的情況
clearTimeout(timer);
timer = setTimeout(() => {
f(...args)
}, t)
}
}
}

444.gif
函數(shù)防抖對于我們代碼層面我們可以用在哪里呢?
在點贊、輸入框校驗、取消點贊、創(chuàng)建訂單等發(fā)送網(wǎng)絡(luò)氫氣的時候,如果我們連續(xù)點擊按鈕,
可能會發(fā)送多次請求。這個對于后臺來說是不允許的。
在鼠標(biāo)每次 resize/scroll 觸發(fā)統(tǒng)計事件。
函數(shù)節(jié)流
與函數(shù)防抖的胞兄,函數(shù)節(jié)流的原理也是大同小異,函數(shù)節(jié)流是在一定時間內(nèi)我只會執(zhí)行一次。
第一次非立即執(zhí)行
export function throttle(f,t){
let timer=true;
return (...arg)=>{
if(!timer){
return;
}
timer=false;
setTimeout(()=>{
f(...arg);
timer=true;
},t)
}
}

555.gif
在效果中,我們點擊了非常多次,但是就只執(zhí)行了4次,因為我規(guī)定的時間是1000ms執(zhí)行一次。這樣也是減少了執(zhí)行次數(shù)。
第一次立即執(zhí)行版本
export function throttleFirstExt(f, t) {
let flag = true;
return (...args) => {
if (flag) {
f(...args);
flag = false;
setTimeout(() => {
flag = true
}, t)
}
}
}

66.gif
這里我們看到了,第一次點擊會立馬執(zhí)行。
合并版
export function throttle(f, t, im = false){
let flag = true;
return (...args)=>{
if(flag){
flag = false
im && f(...args)
setTimeout(() => {
!im && f(...args)
flag = true
},t)
}
}
}

666666.gif
應(yīng)用場景:
DOM 元素的拖拽功能實現(xiàn)(mousemove)
搜索聯(lián)想(keyup)
計算鼠標(biāo)移動的距離(mousemove)
Canvas 模擬畫板功能(mousemove)
射擊游戲的 mousedown/keydown 事件(單位時間只能發(fā)射一顆子彈)
監(jiān)聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 后,只有用戶停止
滾動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次