項目亮點:分析與解決小程序頁面切換過程卡頓的問題
在微信小程序的開發過程中,發現部分頁面的切換動畫在真機調試時,非常卡頓。
頁面切換是指從一個頁面,切換到另外一個頁面。
反復查看了自己的代碼,也沒有發現自己寫了任何非常耗時的操作,因此非常迷惑。
思考了多種方案沒有效果,于是在網上找了一種說法,一篇文章說,在全局樣式中新增如下屬性,就可以解決。
page {
-webkit-overflow-scrolling: touch;
}
病急亂投醫試了一下,很可惜沒有效果。后來想起來了這條屬性是用來解決 iOS 使用 overflow: scroll 滾動不流暢的問題的。
于是,在沒有頭緒的情況下,我啟用了我的找 bug 的終極大招:刪除定位法。
刪除定位法:先刪除部分代碼,再執行頁面,查看卡頓問題是否消失。如果沒有,則刪除其他部分的代碼,直到找到問題代碼為止。
該方法在我的十多年中,所向披靡,戰功顯赫。果不其然,我最終找到了問題所在。
在該頁面組件中,我寫了這樣一段代碼。
useEffect(() => {
ad.current = Taro.createRewardedVideoAd({
adUnitId: ads.ad15
})
...
}, [])
在微信小程序中,createRewardedVideoAd 方法是用來提前創建激勵廣告實例,以便于讀者在點擊按鈕觀看廣告時,廣告已經創建好了,而不用等待那么久。
很顯然,該方法是一個耗時操作。頁面如下:
但是這里一個很具有迷惑性的地方在于,實際上我調用該方法的時機,已經在組件創建完成之后了。
useEffect(() => {
// 組件創建完成之后
}, [])
因此,我就有點懵了,為什么組件創建完成之后調用該方法,還是會卡頓呢?
后面從結果反推之后,我才想明白,微信小程序頁面切換到詳細邏輯應該是。
1. 創建新頁面實例
2. 執行入場動畫 「問題是入場動畫卡頓」
那么此時如果我們在頁面實例創建完成之后立馬執行一個耗時任務,就會跟入場動畫搶占主線程資源,從而導致渲染卡頓。
想明白了這個過程之后,解決的辦法就非常簡單了,我們只需要在入場動畫執行結束之后,再執行耗時任務即可。因此,我們可以使用定時器來推后耗時任務的執行。
useEffect(() => {
setTimeout(() => {
ad.current = Taro.createRewardedVideoAd({
adUnitId: ads.ad15
})
}, 200)
...
}, [])
再保存,重試,發現所有卡頓的頁面都流暢了!完美解決。
在客戶端開發的過程中,還有可能會遇到另外一種情況會導致頁面卡頓。不過這種情況與我這次遇到的這個卡頓的表現會有點不太一樣。這種情況的表現為:
當我點擊按鈕之后,過了很長時間切換動畫才開始執行。
通常情況下,造成這種卡頓的原因是因為頁面初始化時執行的邏輯過多,或者渲染的內容多過,導致初始化時間過長,從而造成反應緩慢。解決的辦法就是通過懶加載延后處理和渲染非首屏內容。
總結
該場景的問題與解決方案可以當做項目亮點在面試中去介紹。無論是找到問題的思路,還是解決的思路都可以展開聊很多。
對于瀏覽器的渲染機制和事件循環了解非常深刻的朋友可以快速想明白卡頓的原因所在,在面試中,基于這個場景延展出來自己對渲染原理的理解,那么你的面試過程將會非常有質量。