性能優化是每個項目都必須重視的,所以在使用uniapp中,將一些性能優化的點記錄下來,在寫代碼的時候需要注意一下:
一、優化數據更新
在 uni-app
中,定義在 data 里面的數據每次變化時都會通知視圖層重新渲染頁面。所以如果不是視圖所需要的變量,可以不定義在 data 中,可在外部定義變量或直接掛載在vue實例上,以避免造成資源浪費。
二、長列表優化
1、長列表中如果每個item有一個點贊按鈕,點擊后點贊數字+1,此時點贊組件必須是一個單獨引用的組件,才能做到差量數據更新,否則會造成整個列表數據重載。
2、長列表中每個item並不一定需要做成組件,取決於你的業務中是否需要差量更新某一行item的數據,如沒有此類需求則不應該引入大量組件。(點擊item后背景變色,屬於css調整,沒有更新data數據和渲染,不涉及這個問題)
3、單個組件中存在大量數據時(比如長列表),在App和小程序端數據更新時會消耗較多時間,建議使用組件對數據進行分頁,將變更限制更小范圍。可以參考:長列表優化示例
我們看一下這個優化示例的核心思路:
優化前:
// bad
<view>
<my-item v-for="(item,index) in list" :key="index" :icon="item.icon" :title="item.title" :detail="item.detail"></my-item>
</view>
下面是優化后的核心內容:
// good
<view>
<my-section v-for="(item,index) in section" :key="index" :begin="item.begin" :end="item.end"></my-section>
</view> import mySection from './my-section.vue'
// my-section.vue
<view>
<my-item v-for="(item,index) in list" :key="index" :icon="item.icon" :title="item.title" :detail="item.detail"></my-item>
</view> created() { this.list = list.slice(this.begin, this.end) }
說一下其優化思路就是:將本來在一個組件內的數據,分布在多個組件內,避免一個組件內的數據量太大導致diff和同步到視圖層耗時太多。
比如一個組件內的100條數據,變成了10個組件內的10條數據,將變更限制了再10條一組的數據組件內。
4、app端nvue的長列表應該使用list組件,有自動的渲染資源回收機制。vue頁面使用頁面滾動的性能,好於使用scroll-view的區域滾動。uni ui封裝了uList組件,在app-nvue下使用了list組件,在其他環境使用頁面滾動,自動適配,強烈推薦開發者使用,避免自己寫的不好產生性能問題。
5、如需要左右滑動的長列表,請在HBuilderX新建uni-app項目選新聞模板,那是一個標桿實現。自己用swiper和scroll-view做很容易引發性能問題
三、減少一次性渲染的節點數量
頁面初始化時,邏輯層如果一次性向視圖層傳遞很大的數據,使視圖層一次性渲染大量節點,可能造成通訊變慢、頁面切換卡頓,所以建議以局部更新頁面的方式渲染頁面。如:服務端返回100條數據,可進行分批加載,一次加載50條,500ms 后進行下一次加載。
四、減少組件數量、減少節點嵌套層級
深層嵌套的節點在頁面初始化構建時往往需要更多的內存占用,並且在遍歷節點時也會更慢些,所以建議減少深層的節點嵌套。
有些nvue頁面在Android低端機上初次渲染時,會看到從上到下的渲染過程,這往往都是因為組件過多導致的。每個組件渲染時都會觸發一次通信,太多組件就會阻塞通信。
五、避免視圖層和邏輯層頻繁進行通訊
- 減少 scroll-view 組件的 scroll 事件監聽,當監聽 scroll-view 的滾動事件時,視圖層會頻繁的向邏輯層發送數據;
- 監聽 scroll-view 組件的滾動事件時,不要實時的改變 scroll-top/scroll-left 屬性,因為監聽滾動時,視圖層向邏輯層通訊,改變 scroll-top/scroll-left 時,邏輯層又向視圖層通訊,這樣就可能造成通訊卡頓。
- 注意 onPageScroll 的使用,onPageScroll 進行監聽時,視圖層會頻繁的向邏輯層發送數據;
- 多使用css動畫,而不是通過js的定時器操作界面做動畫
- 如需在canvas里做跟手操作,app端建議使用renderjs,小程序端建議使用web-view組件。web-view里的頁面沒有邏輯層和視圖層分離的概念,自然也不會有通信折損。
六、優化頁面切換動畫
- 頁面初始化時若存在大量圖片或原生組件渲染和大量數據通訊,會發生新頁面渲染和窗體進入動畫搶資源,造成頁面切換卡頓、掉幀。建議延時100ms~300ms渲染圖片或復雜原生組件,分批進行數據通訊,以減少一次性渲染的節點數量。
- App端動畫效果可以自定義。popin/popout的雙窗體聯動擠壓動畫效果對資源的消耗更大,如果動畫期間頁面里在執行耗時的js,可能會造成動畫掉幀。此時可以使用消耗資源更小的動畫效果,比如slide-in-right/slide-out-right。
- App-nvue和H5,還支持頁面預載,uni.preloadPage,可以提供更好的使用體驗
七、優化背景色閃白
1、如果是新頁面進入時背景閃白
如果頁面背景是深色,在vue頁面中可能會發生新窗體剛開始動畫時是灰白色背景,動畫結束時才變為深色背景,造成閃屏。這是因為webview的背景生效太慢的問題。此時需將樣式寫在 App.vue
里,可以加速頁面樣式渲染速度。App.vue
里面的樣式是全局樣式,每次新開頁面會優先加載 App.vue
里面的樣式,然后加載普通 vue 頁面的樣式。
app端還可以在pages.json的頁面的style里單獨配置頁面原生背景色,比如在globalStyle->style->app-plus->background下配置全局背景色
"style": { "app-plus": { "background":"#000000" } }
另外nvue頁面不存在此問題,也可以更改為nvue頁面。
2、如果是老頁面消失時背景閃白
Android上popin動畫時,老窗體會有一個半透明消失的效果。這個半透明效果的背景色,可以根據需要調節為暗色系。 在pages.json里globalStyle下或指定頁面下,配置app-plus專屬節點,然后配置animationAlphaBGColor屬性。
八、使用nvue代替vue
在 App 端 uni-app
的 nvue 頁面可是基於weex升級改造的原生渲染引擎,實現了頁面原生渲染能力、提高了頁面流暢性。若對頁面性能要求較高可以使用此方式開發,詳見:nvue
九、優化啟動速度
1、工程代碼越多,包括背景圖和本地字體文件越大,對小程序啟動速度有影響,應注意控制體積。組件引用的前景圖不影響性能。app端在v3以前也存在和小程序一樣的問題,但v3起解決了這個問題。
2、App端的 splash 關閉有白屏檢測機制,如果首頁一直白屏或首頁本身就是一個空的中轉頁面,可能會造成 splash 10秒才關閉,可參考此文解決https://ask.dcloud.net.cn/article/35565
3、App端使用v3編譯器,首頁為nvue頁面時,並設置為fast啟動模式,此時App啟動速度最快。
4、App設置為純nvue項目(manifest里設置app-plus下的renderer:"native"),這種項目的啟動速度更快,2秒即可完成啟動。因為它整個應用都使用原生渲染,不加載基於webview的那套框架。
十、優化包體積
1、uni-app發行到小程序時,自帶引擎只有幾十K,主要是一個定制過的vue.js核心庫。如果使用了es6轉es5、css對齊的功能,可能會增大代碼體積,可以配置這些編譯功能是否開啟。
2、uni-app的H5端,自帶了vue.js、vue-router及部分es6 polyfill庫,這部分的體積gzip后只有92k,和web開發使用vue基本一致。而內置組件ui庫(如picker、switch等)、小程序的對齊js api等,相當於一個完善的大型ui庫。但大多數應用不會用到所有內置組件和API。由此uni-app提供了搖樹優化機制,未搖樹優化前的uni-app整體包體積約500k,服務器部署gzip后162k。開啟搖樹優化需在manifest配置,詳情。
3、uni-app的App端,因為自帶了一個獨立v8引擎和小程序框架,所以比HTML5Plus或mui等普通hybrid的App引擎體積要大。Android基礎引擎約9M。App還提供了擴展模塊,比如地圖、藍牙等,打包時如不需要這些模塊,可以裁剪掉,以縮小發行包體積。在 manifest.json-App模塊權限 里可以選擇。
4、App端支持如果選擇純nvue項目(manifest里設置app-plus下的renderer:"native"),包體積可以進一步減少2M左右。
5、App端在HBuilderX 2.7后,App端下掉了非v3的編譯模式,包體積下降了3M。
6、uni-app的App-Android端有so庫的概念,支持不同的cpu類型的so庫越多,包越大。在HBuilderX 2.7以前,Android app默認包含arm32和x86兩個cpu的支持so庫。包體積比較大。如果你在意體積控制,可以在manifest里去掉x86 cpu的支持(manifest可視化界面-App其他設置里選擇cpu),這可以減少包體積到9M。從HBuilderX 2.7起,默認不再包含x86,如有需求請自行在manifest里勾選后打包。一般手機都是arm的,涉及x86 cpu場景很少,包括:個別少見的Android pad、as的模擬器里選擇x86類型。