# 渲染性能優(yōu)化
# 1. 適當(dāng)監(jiān)聽頁面或組件的 scroll 事件
只要用戶在 Page 構(gòu)造時(shí)傳入了 onPageScroll 監(jiān)聽,基礎(chǔ)庫就會認(rèn)為開發(fā)者需要監(jiān)聽頁面 scoll 事件。此時(shí),當(dāng)用戶滑動頁面時(shí),事件會以很高的頻率從視圖層發(fā)送到邏輯層,存在一定的通信開銷。
類似的,對于 <scroll-view>、<page-meta> 等可以通過 bindscroll 監(jiān)聽滑動事件的組件,也會存在這一情況。
正是由于 scroll 事件觸發(fā)的頻率很高,因此開發(fā)者很容易誤用,在使用時(shí)需要注意:
- ? 非必要不監(jiān)聽 scroll 事件;
- ? 在實(shí)現(xiàn)與滾動相關(guān)的動畫時(shí),優(yōu)先考慮滾動驅(qū)動動畫(僅
<scroll-view>)或 WXS 響應(yīng)事件 - ? 不需要監(jiān)聽事件時(shí),Page 構(gòu)造時(shí)應(yīng)不傳入 onPageScroll 函數(shù),而不是留空函數(shù);
- ? 避免在 scroll 事件監(jiān)聽函數(shù)中執(zhí)行復(fù)雜邏輯;
- ? 避免在 scroll 事件監(jiān)聽中頻繁調(diào)用 setData 或同步 API。
Page({
onPageScroll () {} // ?不要保留空函數(shù)
})
Page({
// ? 應(yīng)直接不傳入
})
# 2. 選擇高性能的動畫實(shí)現(xiàn)方式
開發(fā)者在開發(fā)界面動畫時(shí),應(yīng)該選擇高性能的動畫實(shí)現(xiàn)方式。
- ? 優(yōu)先使用 CSS 漸變、CSS 動畫、或小程序框架提供的其他動畫實(shí)現(xiàn)方式完成動畫;
- ? 在一些復(fù)雜場景下,如果上述方式不能滿足,可以使用 WXS 響應(yīng)事件 動態(tài)調(diào)整節(jié)點(diǎn)的 style 屬性做到動畫效果。同時(shí),這種方式也可以根據(jù)用戶的觸摸事件來動態(tài)地生成動畫;
- ? 避免通過連續(xù) setData 改變界面的形式來實(shí)現(xiàn)動畫。雖然實(shí)現(xiàn)起來簡單靈活,但是極易出現(xiàn)較大的延遲或卡頓,甚至導(dǎo)致小程序僵死;
- ? 如果不得不采用 setData 方式,應(yīng)盡可能將頁面的 setData 改為自定義組件中的 setData 來提升性能。
# 3. 使用 IntersectionObserver 監(jiān)聽元素曝光
部分業(yè)務(wù)場景會需要監(jiān)控元素曝光情況,用于進(jìn)行一些頁面狀態(tài)的變更或上報(bào)分析。
- ? 建議使用節(jié)點(diǎn)布局相交狀態(tài)監(jiān)聽 IntersectionObserver 推斷某些節(jié)點(diǎn)是否可見、有多大比例可見;
- ? 避免通過監(jiān)聽 onPageScroll 事件,并在回調(diào)中通過持續(xù)查詢節(jié)點(diǎn)信息 SelectQuery 來判斷元素是否可見。
# 4. 控制 WXML 節(jié)點(diǎn)數(shù)量和層級
一個(gè)太大的 WXML 節(jié)點(diǎn)樹會增加內(nèi)存的使用,樣式重排時(shí)間也會更長,影響體驗(yàn)。
- ? 建議一個(gè)頁面 WXML 節(jié)點(diǎn)數(shù)量應(yīng)少于 1000 個(gè),節(jié)點(diǎn)樹深度少于 30 層,子節(jié)點(diǎn)數(shù)不大于 60 個(gè)。
# 5. 控制在 Page 構(gòu)造時(shí)傳入的自定義數(shù)據(jù)量
為了便于開發(fā),開發(fā)者可以添加任意的函數(shù)或數(shù)據(jù)到 Page 構(gòu)造傳入的 Object 參數(shù)中,并在頁面的函數(shù)內(nèi)用 this 訪問。例如:
Page({
data: {}
userInfo: {} // 自定義數(shù)據(jù)
currentUser: 'Wechat' // 自定義數(shù)據(jù)
onTap() { }
onLoad() {
console.log(this.currentUser)
}
})
為了保證自定義數(shù)據(jù)在不同的頁面實(shí)例中也是不同的實(shí)例,小程序框架會在頁面創(chuàng)建時(shí)對這部分?jǐn)?shù)據(jù)(函數(shù)類型字段除外)做一次深拷貝,如果自定義數(shù)據(jù)過多或過于復(fù)雜,可能帶來很大的開銷。
- ? 對于比較復(fù)雜的數(shù)據(jù)對象,建議在
Page onLoad或Component created時(shí)手動賦值到 this 上,而不是通過 Page 構(gòu)造時(shí)的參數(shù)傳入。
// ? 使用復(fù)雜對象作為自定義數(shù)據(jù)
Page({
onLoad() { }
bigData: { /* A complex object */ },
longList: [ /* A long complex array*/ ]
})
// ? 運(yùn)行時(shí)手動賦值到 this。開發(fā)者可以根據(jù)需要選擇進(jìn)行深拷貝、淺拷貝或不拷貝。
Page({
onLoad() {
this.bigData = { /* A complex object */ },
this.longList = [ /* A long complex array*/ ]
}
})