ReactNative-頁面性能優(yōu)化

生產(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官方文檔
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容