開發(fā)者可以借助 Taro 提供的各種工具對程序性能進行優(yōu)化。
在微信小程序、支付寶小程序和QQ輕應用中,從調(diào)用 Taro.navigateTo 或 Taro.redirectTo 后,到頁面觸發(fā) componentWillMount 會有一定延時。因此一些網(wǎng)絡請求可以提前到發(fā)起跳轉(zhuǎn)前一刻去請求。
Taro 提供了 componentWillPreload 鉤子,它接收頁面跳轉(zhuǎn)的參數(shù)作為參數(shù)??梢园研枰A加載的內(nèi)容通過 return 返回,然后在頁面觸發(fā) componentWillMount 后即可通過 this.$preloadData 獲取到預加載的內(nèi)容。
注意:調(diào)用跳轉(zhuǎn)方法時需要使用絕對路徑,相對路徑不會觸發(fā)此鉤子。
class Index extends Component {
componentWillMount () {
console.log('isFetching: ', this.isFetching)
this.$preloadData
.then(res => {
console.log('res: ', res)
this.isFetching = false
})
}
componentWillPreload (params) {
return this.fetchData(params.url)
}
fetchData () {
this.isFetching = true
...
}
}
用法:this.$preload(key: String | Object, [ value: Any ])
之所以命名為 $preload,因為它也有一點預加載數(shù)據(jù)的意味。
如果覺得每次頁面跳轉(zhuǎn)傳參時,需要先把參數(shù) stringify 后加到 url 的查詢字符串中很繁瑣,可以利用 this.$preload 進行傳參。
另外如果傳入的是下一個頁面的數(shù)據(jù)請求 promise,也有上一點提到的“預加載”功能,也能夠繞過 componentWillMount 延時。不同點主要在于代碼管理,開發(fā)者可酌情使用。
例子:
// 傳入單個參數(shù)
// A 頁面
// 調(diào)用跳轉(zhuǎn)方法前使用 this.$preload
this.$preload('key', 'val')
Taro.navigateTo({ url: '/pages/B/B' })
// B 頁面
// 可以于 this.$router.preload 中訪問到 this.$preload 傳入的參數(shù)
componentWillMount () {
console.log('preload: ', this.$router.preload.key)
}
// 傳入多個參數(shù)
// A 頁面
this.$preload({
x: 1,
y: 2
})
Taro.navigateTo({ url: '/pages/B/B' })
// B 頁面
componentWillMount () {
console.log('preload: ', this.$router.preload)
}
當你清楚在某些情況下組件不需要被重新渲染時,可以通過在 shouldComponentUpdate 鉤子里返回 false 來跳過本次渲染流程。
shouldComponentUpdate (nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true
}
if (this.state.count !== nextState.count) {
return true
}
return false
}
在大多數(shù)情況下,開發(fā)者可以讓組件繼承于 Taro.PureComponent 類,而無需手動實現(xiàn) shouldComponentUpdate。Taro.PureComponent 里實現(xiàn)了 shouldComponentUpdate,它會把新舊 props 和新舊 state 分別做一次淺對比,以避免不必要的渲染。
自 v1.3.0 可用
Taro.memo 是一個高階組件,它和 PureComponent 非常相似。但它適用于函數(shù)式組件,而非 Class 組件。
如果你的函數(shù)組件在給定相同 props 的情況下渲染相同的結(jié)果,那么你可以通過將其包裝在 Taro.memo 中調(diào)用,以此通過記憶組件渲染結(jié)果的方式來提高組件的性能表現(xiàn)。這意味著在這種情況下,Taro 將跳過渲染組件的操作并直接復用最近一次渲染的結(jié)果。
默認情況下其只會對復雜對象做淺層對比(和 PureComponent 行為一致),如果你想要控制對比過程,那么請將自定義的比較函數(shù)通過第二個參數(shù)傳入來實現(xiàn)。
function MyComponent(props) {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把 nextProps 傳入 render 方法的返回結(jié)果與
將 prevProps 傳入 render 方法的返回結(jié)果一致則返回 true,
否則返回 false
*/
}
export default Taro.memo(MyComponent, areEqual);
注意 與 class 組件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 會返回 true;如果 props 不相等,則返回 false。這與 shouldComponentUpdate 方法的返回值相反。
Taro 框架做了一些性能優(yōu)化方面的工作,這部分毋需開發(fā)者手動處理,開發(fā)者可稍做了解。
在真正調(diào)用小程序的 setData 方法之前,Taro 會把頁面或組件的 state 和當前頁面或組件的 data 做一次 diff,只對必要更新的數(shù)據(jù)做 setData,開發(fā)者無需手動優(yōu)化。
例子:
// 新值
const state = {
a: 1,
b: 22,
d: 4,
list: [1],
arr: [1, 'a', true, null, 66],
obj: {
x: 5
},
foo: {
x: 8,
y: 10,
z: 0
}
}
// 舊值
const data = {
a: 1,
b: 2,
c: 3,
list: [1, 2, 3],
arr: [1, 2, 3],
obj: {
x: 10,
y: 8
},
foo: {
x: 'xxx',
y: 10
}
}
diff(data, state)
/**
* diff 結(jié)果
{
b: 22,
d: 4,
list: [ 1 ],
'arr[1]': 'a',
'arr[2]': true,
'arr[3]': null,
'arr[4]': 66,
obj: { x: 5 },
'foo.x': 8,
'foo.z': 0
}
*/
更多建議: