對React、Redux、React-Redux詳細剖析

前言

相信不少新手朋友們對於React、Redux、React-Redux這三者之間的關係和區別確定有不少不解和疑惑。這裏咱們就來詳細的剖析一下它們吧。
react

React:負責組件的UI界面渲染;
Redux:數據處理中心;
React-Redux:鏈接組件和數據中心,也就是把React和Redux聯繫起來。
es6

React

React主要就是用來實現UI界面的,是一個專一於view層的框架。對於一些小項目,若是數據的交互不是不少,徹底能夠只使用React就能很好的實現。
ajax

在傳統的頁面開發模式中,須要屢次的操做DOM來進行頁面的更新,咱們都知道對DOM的操做會形成極大的性能問題。而React的提出就是減小對DOM的操做來提高性能,也就是Virtual DOM。算法

Virtual DOM

Virtual DOM就至關於一個虛擬空間,React就是基於 Virtual DOM 來工做的。
redux

它的工做過程是:當有數據須要進行更新時,會先計算 Virtual DOM ,並和上一次的 Virtual DOM 作對比,獲得DOM結構的區別,而後只會將須要變化的部分批量的更新到真實的DOM上。
api

說到如何去計算Virtual DOM,在React裏面,用到的是react-diff算法。咱們都知道傳統的diff算法是經過循環遞歸對每一個節點進行依次對比,效率低下,算法複雜度達到了 O(n^3),其中 n 是樹中節點的總數。
性能優化

根據react diff策略:
bash

  1. Web UI 中 DOM 節點跨層級的移動操做特別少,能夠忽略不計;
  2. 擁有相同類的兩個組件將會生成類似的樹形結構,擁有不一樣類的兩個組件將會生成不一樣的樹形結構;
  3. 對於同一層級的一組子節點,它們能夠經過惟一 id 進行區分。

React 分別對 tree diff、component diff 以及 element diff 進行了算法優化:
架構

  1. tree diff:對樹進行分層比較,兩棵樹只會對同一層次的節點進行比較
  2. component diff
  • 若是是同一類型的組件,按照原策略繼續比較 virtual DOM tree。
  • 若是不是,則將該組件判斷爲 dirty component,從而替換整個組件下的全部子節點。
  • 對於同一類型的組件,有可能其 Virtual DOM 沒有任何變化,若是可以確切的知道這點那能夠節省大量的 diff 運算時間,所以 React 容許用戶經過 shouldComponentUpdate() 來判斷該組件是否須要進行 diff。
  1. element diff:當節點處於同一層級時,React diff 提供了三種節點操做,分別爲:插入、移動、刪除。

這是整個react diff算法的比較流程圖:
app

react diff

React生命週期

React總共有10個周期函數(render重複一次),這10個函數能夠知足咱們全部對組件操做的需求,利用的好能夠提升開發效率和組件性能。

1、組件在初始化時會觸發5個鉤子函數:

  1. getDefaultProps()

設置默認的props,es6中用 static dufaultProps={} 設置組件的默認屬性。在整個生命週期只執行一次。

  1. getInitialState()

在使用es6的class語法時是沒有這個鉤子函數的,能夠直接在constructor中定義this.state。此時能夠訪問this.props。

  1. componentWillMount() ajax數據的拉取操做,定時器的啓動。

組件初始化時調用,之後組件更新不調用,整個生命週期只調用一次,此時能夠修改state。

  1. render()

React最重要的步驟,建立虛擬dom,進行diff算法,更新dom樹都在此進行。此時就不能更改state了。

  1. componentDidMount() 動畫的啓動,輸入框自動聚焦

組件渲染以後調用,能夠經過this.getDOMNode()獲取和操做dom節點,只調用一次。

2、在更新時也會觸發5個鉤子函數:

  1. componentWillReceivePorps(nextProps)

組件初始化時不調用,組件接受新的props時調用。無論父組件傳遞給子組件的props有沒有改變,都會觸發。

  1. shouldComponentUpdate(nextProps, nextState)

React性能優化很是重要的一環。組件接受新的state或者props時調用,咱們能夠設置在此對比先後兩個props和state是否相同,若是相同則返回false阻止更新,由於相同的屬性狀態必定會生成相同的dom樹,這樣就不須要創造新的dom樹和舊的dom樹進行diff算法對比,節省大量性能,尤爲是在dom結構複雜的時候。不過調用this.forceUpdate會跳過此步驟。

  1. componentWillUpdate(nextProps, nextState)

組件初始化時不調用,只有在組件將要更新時才調用,此時能夠修改state

  1. render()

很少說

  1. componentDidUpdate()

組件初始化時不調用,組件更新完成後調用,此時能夠獲取dom節點。

3、卸載鉤子函數

  1. componentWillUnmount() 定時器的清除

組件將要卸載時調用,一些事件監聽和定時器須要在此時清除。

Redux

Redux是一種架構模式,是由flux發展而來的。

Redux三大原則

  1. 惟一數據源
  2. 狀態只讀
  3. 數據改變只能經過純函數(reducer)完成

Redux核心api

Redux主要由三部分組成:store,reducer,action。

store

Redux的核心是store,它由Redux提供的 createStore(reducer, defaultState) 這個方法生成,生成三個方法,getState(),dispatch(),subscrible()。

store

  • getState():存儲的數據,狀態樹;
  • dispatch(action):分發action,並返回一個action,這是惟一能改變store中數據的方式;
  • subscrible(listener):註冊一個監聽者,store發生變化的時候被調用。

reducer

reducer是一個純函數,它根據previousState和action計算出新的state。
reducer(previousState,action)

reducer

action

action本質上是一個JavaScript對象,其中必須包含一個type字段來表示將要執行的動做,其餘的字段均可以根據需求來自定義。

const ADD_TODO = 'ADD_TODO'
複製代碼
{
  type: ADD_TODO,
  text: 'Build my first Redux app'
}
複製代碼

整合

他們三者之間的交互,能夠由下圖歸納:

React-Redux

Redux 自己和React沒有關係,只是數據處理中心,是React-Redux讓他們聯繫在一塊兒。

React-rRedux提供兩個方法:connect和Provider。

connect

connect鏈接React組件和Redux store。connect其實是一個高階函數,返回一個新的已與 Redux store 鏈接的組件類。

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)
複製代碼

TodoList是 UI 組件,VisibleTodoList就是由 react-redux 經過connect方法自動生成的容器組件。

  1. mapStateToProps:從Redux狀態樹中提取須要的部分做爲props傳遞給當前的組件。
  2. mapDispatchToProps:將須要綁定的響應事件(action)做爲props傳遞到組件上。

Provider

Provider實現store的全局訪問,將store傳給每一個組件。

原理:使用React的context,context能夠實現跨組件之間的傳遞。

總結

下圖闡述了它們三者之間的工做流程:

相關文章
相關標籤/搜索