目錄
一、引出
二、防抖函數(shù)
1.為什么需要防止抖動(dòng)的原因
2.函數(shù)防止抖動(dòng)的原理
3.防抖動(dòng)代碼函數(shù)實(shí)現(xiàn)
4.在小程序當(dāng)中使用的防抖函數(shù)
三、節(jié)流函數(shù)
1.為什么需要節(jié)流的原因
2.函數(shù)節(jié)流的原理
3.節(jié)流函數(shù)代碼的實(shí)現(xiàn)
四、區(qū)別與使用的場(chǎng)景
1.什么時(shí)候會(huì)用到節(jié)流函數(shù)和防抖函數(shù)?
2.防抖函數(shù)和節(jié)流函數(shù)的區(qū)別
五、總結(jié)
一、引出
在寫banner組件的時(shí)候遇到的一個(gè)問題,在寫好banner的輪播圖組件之后,在使用的時(shí)候總是會(huì)偶爾出現(xiàn)一個(gè)抖動(dòng)的效果(以下是一個(gè)出現(xiàn)抽搐的效果圖)
1680162792547.mp4https://five-min.yuque.com/attachments/yuque/0/2023/mp4/32698987/1680188074840-3ad552e2-4a85-408e-8879-8f74ad6bf9db.mp4
這樣讓我個(gè)人感覺就體驗(yàn)不好,更何況是用戶,然后上網(wǎng)查找了一下原因,在微信開發(fā)者文檔中發(fā)現(xiàn)了問題的所在
在此處可以看到在1.4.0開始之后的change事件中添加了一個(gè)source的字段,可以來展示是什么原因?qū)е碌腸hange事件觸發(fā),在使用swiper的時(shí)候不排除會(huì)出現(xiàn)剛剛上面的視頻中的問題,這就是這里的其他原因觸發(fā)了change事件,從而導(dǎo)致的抖動(dòng),這里我的解決方法如下:
swiperChange: function (e: { detail: { current: any; source: any; }; }) {
let current = e.detail.current
let source = e.detail.source
if (source == 'autoplay' || source == 'touch') {
//根據(jù)官方 source 來進(jìn)行判斷swiper的change事件是通過什么來觸發(fā)的,autoplay是自動(dòng)輪播。touch是用戶手動(dòng)滑動(dòng)。其他的就是未知問題。抖動(dòng)問題主要由于未知問題引起的,所以做了限制,只有在自動(dòng)輪播和用戶主動(dòng)觸發(fā)才去改變current值,達(dá)到規(guī)避了抖動(dòng)bug
this.setData({
index: current
})
}
},
然后就對(duì)這一部分進(jìn)行了一個(gè)深入的了解,在網(wǎng)上查找了一下有關(guān)防抖動(dòng)的方法以及產(chǎn)生的原因和進(jìn)行節(jié)流的方法
二、防抖函數(shù)
1.為什么需要防止抖動(dòng)的原因
前端開發(fā)過程中,有一些事件,常見的例如,onresize,scroll,mousemove ,mousehover 等,會(huì)被頻繁觸發(fā)(短時(shí)間內(nèi)多次觸發(fā)),不做限制的話,有可能一秒之內(nèi)執(zhí)行幾十次、幾百次,如果在這些函數(shù)內(nèi)部執(zhí)行了其他函數(shù),尤其是執(zhí)行了操作 DOM 的函數(shù)(瀏覽器操作 DOM 是很耗費(fèi)性能的),那不僅會(huì)浪費(fèi)計(jì)算機(jī)資源,還會(huì)降低程序運(yùn)行速度,甚至造成瀏覽器卡死、崩潰。
2.函數(shù)防止抖動(dòng)的原理
函數(shù)防抖,就是指觸發(fā)事件后,在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果觸發(fā)事件后在 n 秒內(nèi)又觸發(fā)了事件,則會(huì)重新計(jì)算函數(shù)延執(zhí)行時(shí)間,函數(shù)防抖的要點(diǎn),是需要一個(gè) setTimeout 來輔助實(shí)現(xiàn),延遲運(yùn)行需要執(zhí)行的代碼。如果方法多次觸發(fā),則把上次記錄的延遲執(zhí)行代碼用 clearTimeout 清掉,重新開始計(jì)時(shí)。若計(jì)時(shí)期間事件沒有被重新觸發(fā),等延遲時(shí)間計(jì)時(shí)完畢,則執(zhí)行目標(biāo)代碼。
3.防抖動(dòng)代碼函數(shù)實(shí)現(xiàn)
function debounce(fn,wait){
var timer = null;
return function(){
if(timer !== null){
clearTimeout(timer);
}
timer = setTimeout(fn,wait);
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("resize",debounce(handle,1000));
可以用此代碼做一個(gè)例子:在窗口的尺寸發(fā)生變化的時(shí)候會(huì)觸發(fā)resize,然后調(diào)用debounce這個(gè)函數(shù),然后就設(shè)置了一個(gè)倒計(jì)時(shí),當(dāng)重復(fù)多次的觸發(fā)這個(gè)函數(shù)時(shí),當(dāng)時(shí)間沒到設(shè)定時(shí)間的時(shí)候就會(huì)清除倒計(jì)時(shí),然后重新設(shè)置,避免了多次調(diào)用我們想調(diào)用的handle函數(shù)(這里僅做展示使用,實(shí)際上handle函數(shù)沒有實(shí)際的用處,只是為了方便觀察),從而達(dá)到了一個(gè)防抖的效果。
4.在小程序當(dāng)中使用的防抖函數(shù)
內(nèi)部使用,不需要使用外部模塊。
onLoad: function (options) {
console.log(options);
this.debounce = this.debounce();// 防抖函數(shù),在此處初始化
// 若不初始化,函數(shù)主體不執(zhí)行
}
// debounce函數(shù),就是事件觸發(fā)的函數(shù),名字可以隨意取名
debounce : function () {
var timeOut = null;
return () => {
clearTimeout(timeOut);
timeOut = setTimeout(() => {
// 事件函數(shù)中要執(zhí)行的代碼塊
// 改寫原函數(shù)異常方便、簡(jiǎn)潔
}, 300);
}
}
此處的理解與上處的理解類似,也是用倒計(jì)時(shí)的方法防止抖動(dòng)
三、節(jié)流函數(shù)
1.為什么需要節(jié)流的原因
在一個(gè)登錄頁面,如果用戶不停的點(diǎn)擊登錄界面,如果沒有做節(jié)流處理,那么就會(huì)多次向接口發(fā)出請(qǐng)求,會(huì)重復(fù)多次的請(qǐng)求,有的地方還會(huì)造成鬼畜動(dòng)畫,所以這個(gè)時(shí)候就需要節(jié)流來做限制,節(jié)流函數(shù)里面也需要使用定時(shí)器setTimeout,但是這里與防抖的區(qū)別是,節(jié)流是一段時(shí)間內(nèi)不管你觸發(fā)多少次,只響應(yīng)一次。
2.函數(shù)節(jié)流的原理
定義一個(gè)變量,然后通過這個(gè)變量的值來決定是不是執(zhí)行此函數(shù),例如定義begin=true,將要執(zhí)行的部分放入if語句中,用begin當(dāng)做是否進(jìn)入語句的條件,當(dāng)?shù)谝淮吸c(diǎn)擊登錄以后將begin變成flase,那么后面再次進(jìn)行點(diǎn)擊的時(shí)候就不會(huì)進(jìn)入if語句,在語句中使用一個(gè)倒計(jì)時(shí),到達(dá)規(guī)定時(shí)間在將begin的值變回ture就可以了,這樣就可以達(dá)到一個(gè)節(jié)流的效果。(這里的begin也被稱為節(jié)流閥)
3.節(jié)流函數(shù)代碼的實(shí)現(xiàn)
function throttle(fn, interval) {
var enterTime = 0;//觸發(fā)的時(shí)間
var gapTime = interval || 300 ;//間隔時(shí)間,如果interval不傳,則默認(rèn)300ms
return function() {
var context = this;
var backTime = new Date();//第一次函數(shù)return即觸發(fā)的時(shí)間
if (backTime - enterTime > gapTime) {
fn.call(context,arguments);
enterTime = backTime;//賦值給第一次觸發(fā)的時(shí)間,這樣就保存了第二次觸發(fā)的時(shí)間
}
};
}
此處的代碼便于封裝在公共的js代碼中做公共方法調(diào)用
四、區(qū)別與使用的場(chǎng)景
1.什么時(shí)候會(huì)用到節(jié)流函數(shù)和防抖函數(shù)?
- 調(diào)整瀏覽器窗口大小時(shí),resize 次數(shù)過于頻繁,造成計(jì)算過多,此時(shí)需要一次到位(防抖)
- 文本編輯器實(shí)時(shí)保存,當(dāng)無任何更改操作一秒后進(jìn)行保存(防抖)
- 按鈕重復(fù)多次點(diǎn)擊(節(jié)流)
- 百度搜索框,搜索聯(lián)想功能(節(jié)流)
2.防抖函數(shù)和節(jié)流函數(shù)的區(qū)別
防抖函數(shù)是在單位時(shí)間(>1)隨便觸發(fā)多少次事件,只要這次觸發(fā)的時(shí)間與上次觸發(fā)的時(shí)間只差不到1s,都不執(zhí)行;
節(jié)流函數(shù)是在單位時(shí)間(>1)隨便觸發(fā)多少次事件,只要過了1s,就會(huì)執(zhí)行一次。
兩個(gè)函數(shù)都能達(dá)到防止重復(fù)觸發(fā)的功能。但是函數(shù)防抖是 n秒后延遲執(zhí)行;而函數(shù)節(jié)流是立馬執(zhí)行,n秒后再立馬執(zhí)行。
具體的使用主要看需求:
- 當(dāng)我們只需要處理最后一次觸發(fā)事件時(shí),用函數(shù)防抖
- 當(dāng)事件觸發(fā)過于頻繁,我們需要限制事件處理程序的調(diào)用頻率時(shí),用函數(shù)節(jié)流
五、總結(jié)
? ? ? ? 這次小編也是在做小程序開發(fā)的途中發(fā)現(xiàn)的問題就想著記錄一下咯,那今天的分享就到這里結(jié)束 ,咱們下期再見呀!文章來源:http://www.zghlxwxcb.cn/news/detail-759682.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-759682.html
到了這里,關(guān)于微信小程序——swiper抖動(dòng)問題解決以及節(jié)流、防抖的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!