React組件效能最佳化

來源:互聯網
上載者:User

標籤:pcl   const   rem   xtend   ble   相同   提升   segment   快速   

轉自:1190000006100489

React: 一個用於構建使用者介面的JAVASCRIPT庫.

React僅僅專註於UI層;它使用虛擬DOM技術,以保證它UI的高速渲染;它使用單向資料流,因此它資料繫結更加簡單;那麼它內部是如何保持簡單高效的UI渲染呢?

React不直接操作DOM,它在記憶體中維護一個快速響應的DOM描述,render方法返回一個DOM的描述,React能夠計算出兩個DOM描述的差異,然後更新瀏覽器中的DOM。

就是說React在接收到props或者state更新時,React就會通過前面的方式更新UI。就算重新使用ReactDOM.render(<Component />, mountNode),它也只是當作props更新,而不是重新掛載整個組件。所以React整個UI渲染是比較快的。

但是,這裡面有幾個問題

1. 如果更新的props和舊的一樣,這個時候很明顯UI不會變化,但是React還是要進行虛擬DOM的diff,這個diff就是多餘的效能損耗,而且在DOM結構比較複雜的情況,整個diff會花費較長的時間。

2. 既然React總是要進行虛擬DOM的diff,那麼它的diff規則是什嗎?怎麼利用?

PureRenderMixin

針對第一個問題React給我們提供了 PureRenderMixin。如果React組件是純函數的,就是給組件相同的props和state組件就會展現同樣的UI,可以使用這個Minxin來最佳化React組件的效能。

var PureRenderMixin = require(‘react-addons-pure-render-mixin‘);React.createClass({      mixins: [PureRenderMixin],      render: function() {        return <div className={this.props.className}>foo</div>;      }});

 

ES6中的用法是

import PureRenderMixin from ‘react-addons-pure-render-mixin‘;class FooComponent extends React.Component {      constructor(props) {        super(props);        this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);      }      render() {        return <div className={this.props.className}>foo</div>;      }}
 

PureRenderMixin的原理就是它實現了shouldComponentUpdate,在shouldComponentUpdate內它比較當前的props、state和接下來的props、state,當兩者相等的時候返回false,這樣組件就不會進行虛擬DOM的diff。

這裡需要注意:
PureRenderMixin內進行的僅僅是淺比較對象。如果對象包含了複雜的資料結構,深層次的差異可能會產生誤判。僅用於擁有簡單props和state的組件。

shouldComponentUpdate

React雖然提供簡單的PureRenderMixin來提升效能,但是如果有更特殊的需求時怎麼辦?如果組件有複雜的props和state怎麼辦?這個時候就可使用shouldComponentUpdate來進行更加定製化的效能最佳化。

boolean shouldComponentUpdate(object nextProps, object nextState) {    return nexprops.id !== this.props.id;}

在React組件需要更新之前就會調用這個方法,如果這個方法返回false,則組件不更新;如果返回true,則組件更新。在這個方法內部可以通過nextProps和當前props,nextState和當前state的對比決定組件要不要更新。

如果對比的資料結構比較複雜,層次較深,對比的過程也是會有較大效能消耗,又可能得不償失。
這個時候immutable.js就要登場了,也是fb出品,有人說這個架構的意義不亞於React,但是React光芒太強。它能解決複雜資料在deepClone和對比過程中效能損耗。

注意:shouldComponentUpdate在初始化渲染的時候不會調用,但是在使用forceUpdate方法強制更新的時候也不會調用。

render

PureRenderMixin和shouldComponentUpdate的關注點是UI需不需要更新,而render則更多關注虛擬DOM的diff規則了,如何讓diff結果最小化、過程最簡化是render內最佳化的關注點。

React在進行虛擬DOM diff的時候假設:

1、擁有相同類的兩個組件將會產生相似的樹形結構,擁有不同類的兩個組件將會產生不同的樹形結構。
2、可以為元素提供一個唯一的標誌,該元素在不同的渲染過程中保持不變。

DOM結構 

renderA: <div />renderB: <span />=> [removeNode <div />], [insertNode <span />

DOM屬性

renderA: <div id="before" />renderB: <div id="after" />=> [replaceAttribute id "after"]

之前插入DOM

renderA: <div><span>first</span></div>renderB: <div><span>second</span><span>first</span></div>=> [replaceAttribute textContent ‘second‘], [insertNode <span>first</span>]

之前插入DOM,有key的情況

renderA: <div><span key="first">first</span></div>renderB: <div><span key="second">second</span><span key="first">first</span></div>=> [insertNode <span>second</span>]

由於依賴於兩個預判條件,如果這兩個條件都沒有滿足,效能將會大打折扣。

1、diff演算法將不會嘗試匹配不同組件類的子樹。如果發現正在使用的兩個組件類輸出的 DOM 結構非常相似,你可以把這兩個組件類改成一個組件類。

2、如果沒有提供穩定的key(例如通過 Math.random() 產生),所有子樹將會在每次資料更新中重新渲染。

總結

使用PureRenderMixin、shouldComponentUpdate來避免不必要的虛擬DOM diff,在render內部最佳化虛擬DOM的diff速度,以及讓diff結果最小化。

使用immutable.js解決複雜資料diff、clone等問題。

React組件效能最佳化

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.