react性能優化

若是想提升性能就須要知道什麼地方會影響性能?

從過往的經驗和實踐中,影響網頁性能最大的因素就是瀏覽器的重繪和迴流,React背後的虛擬DOM就是儘量的減小瀏覽器的重繪和迴流。react

那在此之上,咱們還能作什麼來防止沒必要要的渲染?編程

在這以前,先跟我一塊兒瞭解下***函數式編程***數組

什麼是函數式編程?

函數式編程起源於數學,假設咱們定義一個加法的方法f,而後改變輸入爲f(1,3),那麼不管這個方法的上下文,不管什麼時間調用多少次,返回結果都是4,用數學表達就是f(x,y) = z,給定輸入x,y做用在f上,始終結果是z瀏覽器

函數式編程講究的三個原則:
1.相同的輸入獲得相同的輸出
2.沒有反作用
3.不依賴外部的狀態(方法內的狀態都只在方法的生命週期內存活,不能在方法中使用共享變量,由於這樣會給方法帶來不可知對的因素)性能優化

那說了這麼多函數式編程有什麼好處呢?

一、函數式編程不依賴外部狀態這一特色,使得咱們能夠利用CPU在分佈式集羣上作並行計算,這對於多種科學計算和資源密集型計算任務是很是核心的一點,讓計算機高效處理這類任務變更的可能 二、相同的輸入獲得相同對的輸出,這讓咱們的代碼變得可預測,能夠很是方便的進行方法級別的測試。bash


說完函數式編程,咱們再回頭說說react的性能優化 《深刻React技術棧中》這樣描述的「 react的設計是有函數式編程的基因的,react組件自己就是純函數,react的createElement方法保證了組件是純淨的,即傳入相同的props獲得必定的虛擬dom,整個過程可預測」。
那麼優化的時候咱們能夠考慮經過拆分組件爲子組件,進而對組件進行更細粒度的控制。數據結構


那接下來就要考慮如何作更細粒度控制,避免屢次無用渲染?

react官方有提供PureComponent類,凡是繼承自這個類的組件,react都會默認在shouldComponentUpdate中替你作這樣一件事,淺比較你的新傳入的props和state是否和如今的props,state。所謂的淺比較就是隻比較props和state中數據的引用地址,引用地址不改變就不會從新渲染。dom

很顯然,問題來了,若是個人數據結構嵌套很深,那豈不是會忽略掉深層次的數據變化,而致使頁面不渲染? 所以react官方提醒道,繼承PureComponent以前最好props,state的結構簡單,對於嵌套深的結構就不要繼承PureComponent了分佈式


那對於深層次的數據結構就這樣放棄使用puerRender了嗎?答案固然不是了,不過先不急着說這個,咱們先說對於結果簡單的能夠繼承PureComponent的咱們要注意些什麼?函數式編程

<MeetingList style = {{'width':'200px','height':'200px','overFlow':'hidden'}}>
  
  <Item items = {this.props.items.filter(item=>item.val>10)}>
複製代碼

這種直接將props設置成對象或者數組的方式,每次都會觸發從新渲染,哪怕值沒有改變。

緣由在於每次調用react組件都會從新建立組件,就算傳入的數組或對象值沒有改變,可是引用地址發生改變了。

解決方法,將對象提早賦值爲常量,不直接使用字面量便可 二、

<input onChange = this.change.bind(this)>
複製代碼

設置props方法並經過bind綁定this的方式,每次都會觸發從新渲染

緣由在於bind會返回一個函數,每次執行bind返回的函數的引用地址改變了

解決辦法採用箭頭函數

三、

class NameItem extends Component {
    render(){
        return (
        <Item >
         <span>a child</span>
         </Item>
        )
    }
}
 
複製代碼

對於設置了子組件的react組件,每次都會從新渲染。

緣由在於,組件編譯以後實際上是這樣的

<Item children = {React.createElement('span',{},'a child')}>
複製代碼

children引用改變了,致使每次都會從新渲染

解決辦法讓NameItem(也就是Item的父組件)繼承pureComponent,根據淺比較策略不會對Item的children進行深比較,也就不會從新渲染


說完簡單的數據結構,咱們再來講下對於props和state比較複雜的數據結構應該怎麼處理,答案是採用immutable。

簡單說下immutable
持久化數據存儲:對immutable對象進行修改的時候都會返回一個新的immutable對象,也就是使用舊數據建立新數據時,包證了舊數據可用 結構化共享:若是樹中一個節點變化,則只修改這個節點和受它影響的父節點,其餘節點實現共享,避免了深拷貝帶來的性能問題

如何使用immutable實現pureRender?

答案是在shouldComponentUpdate中利用immutable進行深比較,拋棄以前的PureComponent的淺比較

import React from 'react';
import {is} from 'immutable';

class App extends Component {
 shouldComponentUpdate(nextProps,nextState){
   const thisProps = this.props || {};
   const thisState = this.state || {};
   if(Object.keys(thisProps).length !== Object.keys(nextProps.keys).length ||
   Object.keys(thisProps).length !== Object.keys(nextProps.keys).length){
       return true;
   }

   for(const key in nextProps){
     if(nextProps.hasOwnProperty(key) && !is(thisProps[key],nextProps[key])){
       return true;
     }
   }

   for(const key in nextState){
     if(nextState.hasOwnProperty(key) && !is(thisState[key],nextState[key])){
       return true;
     }
   }

   return false;

 }
}
複製代碼