React As Far As I Know

##寫在開始以前javascript

前端歷來都不缺乏輪子,幾乎天天都有新的輪子被創造出來。滿目琳琅,數不勝數。可是當下最時興的輪子恐怕就是React。從github上來看,目前React的watch數:1521,start數:21522,fork數:3018。對比一下目前也相對時興的一些技術,好比說Go,三個指標分別爲:754786656;在好比說Docker1848213844996。因而可知React的火熱程度。有幸去年十二月份也開始接觸React,陸陸續續接觸React也有小半年的時間了,是時候停下來把本身知道的,已經忘記的總結一下記錄下來,萬一能對剛入手React的同仁有點幫助,那更是夢寐以求。html


##簡單介紹一下React 官方文檔的介紹是這樣的:React是用來構建用戶界面額Javascript庫。前端的框架都已經這麼多了,大家Facebook還開源React做甚?下邊多是官方給出的答案:咱們和別的框架不同,咱們有如下特性: 1.咱們不是一個傳統的前端MVC框架,咱們只關注V這一層。咱們有component的理念,用戶能夠隨便定義和重用component來構建頁面。假設你的項目剛剛開始你可使用React,若是一年以前你不認識React誤選了Angular,React仍是能夠踏踏實實爲你作好UI的工做。就是這麼任性。 2.React定義了本身的虛擬DOM。咱們發現了這樣的一個事實:Javascript的執行速度是很是快的,可是DOM操做每每是比較耗時的。因此,咱們提出了虛擬DOM的理念。經過虛擬DOM咱們會過濾掉不少沒必要要的DOM操做。咱們要作性能最高的前端框架。 3.咱們的數據流是單向的,咱們這樣的機制能夠幫助程序員快速定位bug。前端

看到這樣的框架能不動心嗎,以上咱們通通表明Facebook。java

提綱: -Jsx語法入門 -React的構建基礎-Component -深刻理解Component -Flux框架入門 //TODO -Fluxthis框架入門 //TODO -爲何React這麼快[Virtual Dom] //TODOreact


Jsx語法入門

Jsx是React工具鏈中最基礎的一環。Jsx是構建React Component的有力工具。Jsx之於React猶如Swift之於iOS。Jsx把javascript和xml揉在一塊兒,在javascript中寫xml標籤。前幾天逛論壇,有人提出了把html寫到javascript文件中,大大影響了代碼的美觀和可讀性。雖然,React提供了使用pure javascript的方式,可是,事後你會發現Jsx纔是最高效的。而且寫代碼時費費腦子組織一下代碼,代碼的可讀性是很是好滴。因此那個帖子中有人這樣回覆:git

你能夠嘗試非Jsx的寫法,可是早晚你會發現,其實Jsx更適合你。程序員

言歸正傳,首先看一個簡單的例子來熟悉一下jsx語法。github

var Ul = React.createClass({
  render: function() {
  	var lis = [1, 2, 3].map(x => <li>{x}</li>)
        return (
            <ul className="ul-class">
        	{lis}
            </ul>
        );
  }
});

//編譯後
var Ul = React.createClass({displayName: "Ul", render: function() {
  	var lis = [1, 2, 3].map(function(x)  {return React.createElement("li", null, x);})
        return (
        	React.createElement("ul", {className: "ul-class"}, lis);
        );
  }
});

這個示例很是簡單,展現1到3的數字列表。看一下render函數,首先它定義了一個lis的變量,這個變量記錄了全部的li條目,每一個li都是一個<li>標籤。而後,return中的<ul>標籤中使用了該變量。很簡短的一個例子,對比一下編譯後的代碼,仍是能夠發現Jsx的版本是比較簡潔明瞭的。若是想在html中插入javascript代碼,使用{}就好了。好比{ lis }, {true ? ... : ... }, {/* comment */}這些都是支持的。可是下邊的這些狀況就是不能夠的了{if(true) ... }, 雖然Jsx支持三元表達式,可是不支持if;{var x = 1}這也是不能夠的。那咱們在{}內部在嵌套一個{}嗎?對不起這樣作也不行。golang

有時候我本身也納悶:爲何Jsx支持的語法這麼匱乏。咱們來看一下Jsx不支持的幾種狀況: 1.{var x = 1}。爲何要在html elements中間聲明變量呢?仔細想一下數據其實均可以放到javascript代碼中處理,html中只對處理好的結果作一個引用。{lis}這樣也就夠了。ajax

2.{if(true)....}。在javascript中if-else是沒有返回值的,是有兩個表達式組成的複雜表達式,因此不支持if-else也很合理。一樣把if-else邏輯放到javascript中去。

3.{"x"} {"y"}。這個例子是我幫一個同事調代碼是看到的。這case編譯是不會有問題的,可是結果不是你想要的結果。強調一下:確保在html中的每一句javascript簡單,能一句話搞定的不要搞成兩句。

###我平常寫Jsx的一些經驗 1.確保每一個render返回的結構清晰簡單。要作到這一點要遵循下邊兩個要求:不要在html中混入複雜的處理邏輯提取Component。 對於第一點,html和javascript雜糅在一塊兒確定會致使代碼可讀性下降,React專一於UI,因此每一個Component除了名字要表明它的意義以外,它render的html也要一目瞭然。 第二點,不要搞超大Component。每個Component都是一個函數,儘可能讓每個Component只作一件事情(keep it simple)。Component有View Component和Business Component之分。這裏着重指的是View Component,Business Component的複雜性由具體業務決定。Component小了,相對的html結構也就簡單了。

2.處理頁面邏輯時不要手動修改props。把props當作一個不可變的屬性對待,不要直接就這props作數據處理。

3.還有一些code style上的建議,具體參考這篇文章吧。


##React的構建基礎-Component

Component是React的核心理念。在React的世界裏只有Component的概念,Component是構建應用的基礎。就像React文檔中給出的例子,搭建這樣的一個應用咱們須要這幾種Component的組合。這是頗有意思的事情,讓咱們寫前端的時候再也不關注這個頁面應該有哪些div組成,每一個div往哪擺這些瑣碎的問題。而是站在一個更高的level對咱們的應用作設計和規劃。(我是一個前端門外漢,主觀感覺,說錯了不負責任)

每一個Component都是一個狀態機,也就是說你把足球,籃球和棒球傳入了展現Component,那麼你必定會獲得三種球類的展現。頁面輸出依賴於傳入的數據,頁面和傳入的數據是保持一致性的。同時這種思想也符合函數編程思想,對於一個函數(component也是)相應的輸入總能獲得指望的輸出。這對於程序員的好處就是對本身寫的代碼更放心。下面介紹些Component的使用。

thinking in react

###Component經常使用Api及生命週期

1.render:是Component必需要有的。render方法可使一段html(注意,這段html必須由一個標籤包圍,而且標籤要閉合),同時也能夠引用其餘的Component。render()方法必須是無反作用的,不可以修改Component的狀態。

2.getInitialState:一些Component是擁有本身的狀態的,這些狀態要實如今getInitialState中聲明。好比:

render: function() {
    return {
        name: "default"
    };
}

只有聲明過以後的state才能夠經過this.state.name使用。getInitialState函數只在Component掛在以前調用一次。

3.compomentDidMount:這個函數很是有用。若是Component依賴於後臺數據,通常ajaxcall都會放在這個函數中。

4.propsTypes:propsTypes不是必須的,若是你須要嚴格的規定某個props的類型,以及指明某個props是不是必須的,可使用該函數。

5.shouldComponentUpdate:這個函數是性能相關的函數,95%的狀況下你不須要管它,可是須要知道它是幹什麼的。當Component的狀態改變的時候,須要從新render一次,你能夠經過這個函數控制Component是否應該從新render。

###props和state

React是很是容易上手的,哪怕是初體驗者恐怕半個小時內都能跑起一兩個例子。可是,用好React就得花一些功夫,其中state和props這兩個概念以爲值得你花時間去研究。不管是props仍是state都是都是提供數據的,可是props和state是徹底不一樣的兩種東西。

在說props和state以前先說一下Stateful Component和Stateless Component。

Stateless Component:這類Component能夠說是Pure UI Component。它主要用做展現數據(圖1中紅框標記的Component),或者是一些簡單的HTML標籤的組合(圖1中藍框標記的Component)。

Stateful Component:這類Component主要負責前端後臺的溝通(好比,發送ajax call),和響應頁面事件(好比表單驗證Component,須要一個state記錄用戶的輸入)。

回到props和state上來:

props:props的職責的爲Component提供配置信息,由Component外部提供。props是public的,React提供了propsTypes函數來限制每一個props的類型,以及是否可選的(optional)。還有props是隻讀的,不要在Component內部手動修改props。

好比有這樣一個Component:顯示一個帶標題的輸入框。這樣的Component在表單場景中很常見,複用性很是高。那這個Component的title屬性應該經過props傳給Component。

state:state寄生在Component內部,是Component私有的屬性,state使用前必須經過getInitialState進行聲明並初始化。當狀態改變的時候調須要掉用setState使最新狀態生效。每次調用setState方法都會觸發Component從新render,切記setState方法不能在render方法中調用。state是專門針對Stateful Component的,對於Stateless 的Component徹底能夠忽略該屬性。

###Thinking In React

先讓你們看一個例子

條件語句在JSX裏太痛苦了,把條件提到前面的話模板太亂,用?:的話條件一多就寫要崩,若是有個庫能夠這樣用:

<div className="content-body">
    {
        case()
            .when(!this.state.users, <div>Loading</div>)
            .when(!this.state.users.length, () => <div className="mute-text">No users</div>)
            .else(() => this.state.map(user => { ... }) )
        .end()
    }
</div>

首先,來分析一下他想要實現什麼功能:應該是經過ajax call拿到一組user,而後把這些user展現到頁面上,還有ajax pending時頁面顯示loading。很是常見的一個例子。而後咱們看一下他的實現:根據user 狀態3種不一樣的值來控制頁面不一樣的展現結果。這種實現方式是能夠解決問題的,可是這種思路不是特別的React。先給出一個比較合理的實現,作一個對比:

React.createClass({
  getInitialState: function() {
    return {users: [], isDataReady: false} ;//when ajax done set `isDataReady` to true
  },

  render: function() {
    var usersTemplates = this.state.users.length > 0 ? this.state.users.map(user => <User user={user} />) : "no user";

    return (
      <div>
        <Splash show={ this.state.isDataReady}> //this template`s can handle if shows depends on isDataReady state
        { usersTemplates } //show users
      </div>
    )
  }
});

接着再來看一下上邊的實現有哪些欠妥的地方: 1.對state的使用不是特別清楚,沒有弄明白到底這個Component到底應該有哪些state。首先,這個Component有三種顯示:Loading,No User,Users。第一種是在ajax call pending時的顯示,當load到數據以後第一種顯示切換爲第二或第三種顯示(依據是否有users)。那麼這個Component到底應該有哪幾個state呢?首先,users這個狀態確定須要;其次,isDataReady狀態用來記錄ajax call是否完成。

2.Component的抽象不清晰。實現這個需求至少須要兩個組件:Splash和User。Splash在loading時顯示,而且Splash是一個很是通用的組件,能夠作到全站複用。有沒有必要再抽一個Users的Component?這個可抽可不抽,主要看當前這個Component的功能及複雜性。

參考: Props vs State Thinking in React React Tips and Best Practices

相關文章
相關標籤/搜索