React 性能優化總結

React 性能優化總結

總結了如下幾個方面在react上的性能優化react

  • 常見的性能問題場景
    web

  • 時刻注意代碼的潛在性能問題
    chrome

  • 注意可重構的代碼,組件化
    redux

  • 瞭解如何使用工具定位性能問題
    canvas

常見的性能問題場景

  • JavaScript 語言採用的是單線程模型,也就是說,全部任務只能在一個線程上完成,一次只能作一件事。若是頁面比較複雜,添加了大量的計算,而且還添加了Canvas(Canvas 是一個很是受歡迎的表現方式,同時也是WebGL的入口。它能繪製圖形,圖片,展現動畫,甚至是處理視頻內容)的繪製,那頁面加載可能會卡頓,有可能會呈現出假死狀態。
    數組


    解決方案:在Worker中使用OffscreenCanvas或者將頁面渲染時大量的計算放在Worker中。 首先咱們先了解幾個概念(以在Worker中用OffscreenCanvas爲列)
    瀏覽器

    • Workers 是一個Web版的線程——它容許你在幕後運行你的代碼。將你的一部分代碼放到Worker中能夠給你的主線程更多的空閒時間,這能夠提升你的用戶體驗度性能優化

    • OffscreenCanvas並不依賴DOM。bash

      1. 一種是在 Worker 線程建立一個 OffscreenCanvas 作後臺渲染,而後再把渲染好的緩衝區 Transfer 回主線程顯示。
      2. 一種是主線程從當前 DOM 樹中的 Canvas 元素產生一個 OffscreenCanvas,再把這個 OffscreenCanvas 發送給 Worker 線程進行渲染,渲染的結果直接 Commit 到瀏覽器的 Display Compositor 輸出到當前窗口,至關於在 Worker 線程直接更新 Canvas 元素的內容。
    • OffscreenCanvas學習文檔
      另外web workers學習文檔請去官網瞭解
      框架

      總結: 學習成本比較低,在耗性能的計算和渲染放在Worker中,確實能提高用戶體驗度

  • dom節點層次多,並且深,更改state或者更改redux,致使與該數據無相關的dom節點屢次render。

  • js處理數據過於複雜。定義的狀態數據層次過於深。致使對比或者遍歷數據消耗性能。

時刻注意代碼的潛在性能問題

  • {...this.props} 不要濫用,請只傳遞component須要的props,傳得太多,或者層次傳得太深,都會加劇shouldComponentUpdate裏面的數據比較負擔。

  • 方法綁定的使用

    1. 方法直接綁定在dom節點中
    <div onClick={this.tap.bind(this)} /> 
    複製代碼
    1. 方法綁定放在constructor中
    constructor(props) {
        super(props);
        this.tap= this.tap.bind(this);
    }
    複製代碼
    1. 箭頭函數
    tap = ()=>{};
    <div onClick={this.tap} />
    複製代碼
    tap =(value)=> {};
    <div onClik={()=>this.tap(value)} />
    複製代碼

    總結:
    1.因爲綁定是在render中執行,而render是會執行屢次的,每次bind和箭頭函數都會產生一個新的函數,於是帶來了額外的開銷
    2.使用構造器bind的方法,每一個實例均可以有效地共享函數體,從而更加有效的使用內存。但當要綁定的函數較多時,這種方法又顯得相對的枯燥和無聊。因此,在知道實例很少,函數體不大的前提下,使用箭頭函數更加快捷。
    3.綜合三種寫法,第三種是目前最優寫法

  • 數組遍歷map

    map裏面添加key,而且key不要使用index(可變的),儘可能使用穩定常量做爲key。使用index做爲key,只是會讓代碼不報錯,其餘一無可取。
    每當組件的props或state改變時, React會從新建立一個virtual DOM, 與上一個做對比, 若是發現兩個virtual DOM不徹底相同, 則React就會作reconcile, 把有差別的地方更新到真實的DOM上。
    使用常量做爲key
    複製代碼
  • 儘可能少用不可控的refs、DOM操做。

  • props和state的數據儘量簡單明瞭,扁平化。便於數據對比,數組遍歷從而減少帶來的性能消耗。

  • 使用return null而不是CSS的display:none來控制節點的顯示隱藏。保證同一時間頁面的DOM節點儘量的少。

注意可重構的代碼,組件化

  • 組件分類
  • 可複用性
  • 足夠細
  • 耦合度低

組件分類

在開發前期能夠根據業務場景將組件分類

  • 展現類組件(沒有任何交互,只是純展現數據)
  • 交互類組件(頁面交互操做比較頻繁)
  • 數據類組件(好比dva,redux,基本在搭建框架時已模塊化)
  • 高階組件(對原有組件的保護,更利於後續的迭代開發)

可複用性

這裏咱們就要說一下有狀態組件和無狀態組件的區別了 就如上所說的展現類組件,這種咱們就能夠把它歸類爲無狀態組件,舉個列子

import React from 'react';

const PicModal = props => {
  const { title = '', content = '', picUrl = '', deviceName = '' } = props;
  return (
    <div>
      <span>title</span>
      <span>content</span>
      <span>deviceName</span>
      {picUrl !== '' ? <img src={picUrl}/> : null}
    </div>
  );
};

export default PicModal;
複製代碼

這樣咱們就能夠本身封裝一個modal組件,根據業務場景不斷的迭代優化。 而上面的交互類組件大多數狀況下都是有狀態組件,維護自身的狀態值。可是要實現可複用性,組件之間的耦合度確定是要低的。組件本身控制本身內部的state。這樣setState只用局部更新視圖。減少性能消耗。
注意:千萬不要在父組件定義state,傳值給子組件。
1.下降組件之間的耦合度
2.便於後續的組件迭代

足夠細

根據業務場景將組件拆分的足夠細。

  • 可讀性強
  • 維護性高
  • 便於複用

耦合度低

下面舉一個移動端的列子,web端大多數都會有這種狀況,點擊項目id列表中projectId,projectList改變。

解決方案:組件1和組件2是經過projectId進行聯動。若是咱們拿到這個需求,首先組件化1和2,組件1經過點擊id,在父組件中執行getProjectList方法,從而實現渲染組件2。根據組件1中id的state渲染組件1


這樣父組件與子組件耦合度很低,子組件本身維護本身的狀態值
兄弟組件之間互不影響,經過父組件通訊


若是拆分業務組件的思路不清晰,盲目的將狀態值放在父組件中,這樣耦合度會大大增長,組件的複用性會大大下降。

瞭解如何使用工具定位性能問題

  • chrome插件 redux devtools
  • chrome插件 react devtools
相關文章
相關標籤/搜索