生產(chǎn)環(huán)境下日志輸出禁用:
- 接入babel-plugin-transform-remove-console
npm install babel-plugin-transform-remove-console --save-dev - 配置.babelrc
{
...
"plugins": [
...
],
"env": {"production": {
"plugins": [["transform-remove-console", {"exclude": ["error"]}]]
}
}
}
采用setNativeProps
在RN中,如果需要頻繁刷新view,建議使用setNativeProps,避免使用setState導(dǎo)致的頻繁render。
類似如下頂部tab的透明度漸變,就適用這種情況:

官方原文建議
在(不得不)頻繁刷新而又遇到了性能瓶頸的時候。 直接操作組件并不是應(yīng)該經(jīng)常使用的工具。一般來說只是用來創(chuàng)建連續(xù)的動畫,同時避免渲染組件結(jié)構(gòu)和同步太多視圖變化所帶來的大量開銷。setNativeProps 是一個“簡單粗暴”的方法,它直接在底層(DOM、UIView等)而不是React組件中記錄state,這樣會使代碼邏輯難以理清。所以在使用這個方法之前,請盡量先嘗試用setState 和shouldComponentUpdate方法來解決問題。
使用PureComponent或shouldComponentUpdate
PureComponent
當(dāng)組件更新時,如果組件的 props 和 state 都沒發(fā)生改變, render 方法就不會觸發(fā),省去 Virtual DOM 的生成和比對過程,達(dá)到提升性能的目的。
具體原理是 在shouldComponentUpdate回調(diào)中,對oldState和newState 及 oldProps和newProps進(jìn)行淺比較,如不同,才return true,進(jìn)而回調(diào)render。
重寫shouldComponentUpdate
shouldComponentUpdate() {
return this.state.update;
}
控制在需要的時候才去刷新,根據(jù)需求或者業(yè)務(wù)去控制。
Android硬件加速
通過啟用View的renderToHardwareTextureAndroid屬性 為true,可以開啟View的硬件加速。( 決定這個視圖是否要把它自己(以及所有的子視圖)渲染到一個 GPU 上的硬件紋理中。)
在 Android 上,這對于只修改不透明度、旋轉(zhuǎn)、位移、或縮放的動畫和交互十分有用:在這些情況下,視圖不必每次都重新繪制,顯示列表也不需要重新執(zhí)行。紋理可以被重用于不同的參數(shù)。負(fù)面作用是這會大量消耗顯存,所以當(dāng)交互/動畫結(jié)束后應(yīng)該把此屬性設(shè)置回 false。
?shouldRasterizeIOS在iOS上有個shouldRasterizeIOS屬性,可以設(shè)置該view在被渲染到屏幕之前,先繪制到一個位圖上,這個我理解和Android中的雙緩沖區(qū)比較想像。
這個屬性對于不會修改組件和子視圖尺寸的動畫和交互十分有用。舉例來說,當(dāng)我們移動一個靜態(tài)視圖的位置的時候,預(yù)渲染允許渲染器重用一個緩存了靜態(tài)視圖的位圖,并快速合成。
長列表加載
使用用復(fù)用性更強(qiáng)的FlatList或SectionList
FlatList或SectionList優(yōu)化:
- Item采用PureComponent或重寫shouldComponentUpdate
- getItemLayout 如果行高是固定的,可以使用getItemLayout,避免動態(tài)測量內(nèi)容尺寸的開銷。
首屏進(jìn)入時間優(yōu)化:
減少bundle包大小
- 圖片壓縮;
- 把不重要圖片上傳到圖床
- 分包加載(這個說來話長,要單獨(dú)講了)
懶加載
JS在執(zhí)行import時有時很需要時間,首屏不需要展示的組件可以懶加載
import React, { Component } from 'react';
import { TouchableOpacity, View, Text } from 'react-native';
// 先把這個組件賦值為null
let VeryExpensive = null;
export default class Optimized extends Component {
state = { needsExpensive: false };
didPress = () => {
if (VeryExpensive == null) {
// 真正需要這個組件的時候才加載
VeryExpensive = require('./VeryExpensive').default;
}
this.setState(() => ({
needsExpensive: true,
}));
};
render() {
return (
<View style={{ marginTop: 20 }}>
<TouchableOpacity onPress={this.didPress}>
<Text>Load</Text>
</TouchableOpacity>
// 根據(jù)需要判斷是否渲染該組件
{this.state.needsExpensive ? <VeryExpensive /> : null}
</View>
);
}
}
使用BindingX
理論上任何 "頻繁通信+UI更新" 的場景都可以使用BindingX來優(yōu)化卡頓問題。
安裝: npm install react-native-bindingx --save
適用場景:
- 監(jiān)聽
pan手勢,更新UI。 - 監(jiān)聽滾動容器(如List)的onscroll事件,更新UI。
- 監(jiān)聽設(shè)備傳感器方向變化,更新UI。
- 動畫。(即監(jiān)聽設(shè)備的每一幀的屏幕刷新回調(diào)事件,更新UI)。
BindingX官方文檔