本文是我學習react的階段性小結,若是看官你是react資深玩家,那麼還請就此打住移步他處,若是你想給一些建議和指導,那麼還請輕拍~html
目前團隊內對react的使用很是廣泛,以前對react使用很少,正好我目前在作的項目也在使用react+redux,藉着這個機會系統的學習下react+redux。前端
react是一個JavaScript類庫,經過react,咱們能夠構建可組合的UI,也就是說,咱們能夠經過重用組件來組合出咱們的UI。能夠說react的核心即是組件,目的就是重用和組合。react
官網有這樣一句話.git
We built React to solve one problem: building large applications with data that changes over time.github
咱們知道,隨着應用規模的不斷擴大,UI背後的數據模型愈來愈複雜,業務邏輯也不可避免的變得愈來愈複雜,以致於複雜到僅僅是修復一個簡單的問題咱們就須要投入大量的時間和精力。編程
現有的不少前端框架都在致力於解決這樣的問題,基本思想都是基於MV*的模式,這裏有一篇文章詳細介紹了各類MV*模式的原理和優缺點。redux
那麼,react是如何解決這個問題的呢?
react聚焦於組件。react理解的組件實際上就是一個狀態機。當組件處於某個狀態時,就輸出這個狀態對應的界面。在React中,咱們只須要簡單的去更新某個組件的狀態,而後輸出基於新狀態的整個界面。React負責以最高效的方式去比較兩個界面並更新DOM樹。至於如何對組件以外的數據進行管理,react提出了flux方案。segmentfault
前面咱們知道,react組件是一個狀態機器,以狀態爲輸入,以界面爲輸出。在不一樣狀態切換之間,react提供了一系列的生命週期方法,大體能夠分爲以下三類:api
react組件在實例化時會依次調用以下組件方法:前端框架
當react組件被實例化後,用戶的一些操做會致使組件狀態的更新,此時以下方法將依次被調用:
在組件銷燬的時候,會調用以下組件方法:
這裏有一段簡單的測試代碼:
var ChildComponent = React.createClass({ render: function () { console.log("call render"); return ( <div> {this.props.data} </div> ); }, componentWillReceiveProps: function () { console.log("call componentWillReceiveProps"); }, shouldComponentUpdate: function () { console.log("call shouldComponentUpdate"); return true; }, componentWillUpdate: function () { console.log("call componentWillUpdate"); }, componentDidUpdate: function () { console.log("call componentDidUpdate"); }, componentWillUnmount: function () { console.log("call componentWillUnmount"); } }); var MyComponent = React.createClass( { getDefaultProps: function () { // console.log("call getDefaultProps"); return { className: "test" }; }, getInitialState: function () { // console.log("call getInitialState"); // console.log("log prop: ", this.props); return { text: "something" }; }, componentWillMount: function () { console.log("call componentWillMount"); }, componentDidMount: function () { console.log("call componentDidMount"); }, render: function () { console.log("call render"); var child; if (this.state.text === "after click") { child = null; } else { child = <ChildComponent data={this.state.text} />; } return ( <div className={this.props.className} onClick={this.handleClick}> {child} </div> ); }, handleClick: function () { this.setState({ text: "after click" }); } }); ReactDOM.render( <MyComponent />, document.getElementById("content") );
關於API的部分,官網已經給了詳盡的說明,此處略去。
JSX是react的核心組件之一。react堅信標籤和生成它的代碼是緊密相連的,若是展現邏輯很是複雜(事實上大多數狀況下都是),那麼經過模板語言來實現這些邏輯會產生大量代碼,因而react作了一個很是簡單、可選相似HTML語法 ,經過函數調用便可生成模板的編譯器,稱爲JSX。
經過JSX,咱們能夠用HTML的語法建立JavaScript對象。好比,爲了在React中生成一個連接,經過純JavaScript能夠這麼寫:
React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello React!')
經過JSX這就變成了:
<a href="http://facebook.github.io/react/">Hello React!</a>
咱們發現經過JSX,代碼會更加簡潔和易讀,使用起來也更加方便。
更過關於JSX的內容請參考官方文檔.
前面咱們知道,react的核心就是組件,目的就是重用和組合。那麼咱們如何才能作到組件可重用和組合呢?
首先說說組合。
組合描述的是一種從屬關係,在面向對象編程中被描述爲HAS-A的關係。
在react中,咱們經過以下的代碼實現組合:
<Parent><Child data={this.props.childData} /></Parent>
在這個例子中,Parent中有一個Child的實例,Parent是擁有着。在組件中,組件不能改變自身的props,組件的props始終與組件的擁有着設置的保持一致。
這裏就有一個很是有趣的事情。組件的props永遠來自於組件的擁有者(默認的除外),組件的擁有者能夠經過它的props 或state計算出一些值,並把這些值綁定到它們擁有的組件的props上,即在react中,數據就經過props的方式從組件的擁有者單向的流向了組件。
再說說可重用。
可重用,第一感受就是有一層抽象含義在其中。咱們從若干類似的組件中抽象出一層接口,實現公共的組件。換句話說,咱們把一些頁面上通用的設計元素(按鈕、表單等)拆分紅接口設計良好的可複用組件。每個組件通過良好的測試和封裝,那麼在下次開發類似的頁面的時候,能夠寫更少的代碼,也意味着更高的開發效率和更高的質量。
更多關於組件組合和可重用的說明,請參考複合組件和可重用組件。
前面知道,react關注組件,組件的狀態發生變化,react會更新頁面dom,在這其中缺失了對數據的管理。當應用的規模愈來愈大,咱們面臨的挑戰正是來源於對數據的管理和頁面的更新。如今react解決了頁面更新的問題,那麼數據管理如何解決呢?
react提出「單向數據流」的概念,並在此基礎上推出flux應用體系架構。
Flux應用主要包括三部分:dispatcher、store和views(React components)。Dispatcher,stores和views是擁有清晰的輸入輸出的獨立節點,而actions是包含了新的數據和身份屬性的簡單對象。當用戶與React視圖交互的時候,視圖會經過中樞dispatcher產生一個action。而後大量的保存着應用數據和業務邏輯的視圖接收到冒泡的action,更新全部受影響的view。
下圖是flux的結構圖:
原圖來自react官網
說到flux,就不得不提redux了,這裏貼幾篇關於flux、reflux和redux的對比文章。
也貼一張redux的結構圖吧:
原圖來自《UNIDIRECTIONAL USER INTERFACE ARCHITECTURES》
我的感受,redux作了更加完善的封裝,開發者不用過多的關注action怎麼dispatch到store那裏,也不用關注store如何觸發更新view的邏輯,開發者須要作的就是根據本身的實際需求,知道何時產生什麼樣的action以及如何處理這些action就能夠了,其餘的就交給redux吧~