## 第五步: React速成教程
React是一個用于構建UI的JS庫。你可以說它的競爭對手有AngularJS,Ember.js,Backbone和Polymer,盡管React專注的領域要小得多。React僅僅是MVC架構中的V,即視圖層。
那么,React有什么特殊的呢?
React的組件使用特定的聲明式樣式書寫,不像jQuery或其它傳統JS庫,你不與DOM直接交互。當背后的數據改變時,React接管所有的UI更新。
React還非常快,這歸功于Virtual DOM和幕后的diff算法。當數據改變時,React計算所需要操作的最少的DOM,然后高效的重新渲染組件。比如,如果頁面上有10000個已經渲染的元素,但只有一個元素改變,React將僅僅更新其中一個DOM,這是React為何能高效的重新渲染整個組件的原因。
React其它令人矚目的特性包括:
* 可組合性。小的組件可以組合成大的、復雜的組件。
* 相對易于學習。需要學習的并不多,并且它不像AngularJS或Ember.js那樣有龐大的文檔。
* 服務端渲染。讓我們能輕松的構建[同型JS應用(Isomorphic JavaScript apps)](https://medium.com/@mjackson/universal-javascript-4761051b7ae9)。
* 最有幫助的錯誤和警告提示,是我從未在其它JS庫中見到過的。
* 組件是自包含的。標記、行為(甚至[樣式](http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html))都在同一個地方,讓組件非常易于重用。
我非常喜歡[React v0.14 Beta 1發布](http://facebook.github.io/react/blog/2015/07/03/react-v0.14-beta-1.html)中的這段話,講了React到底是什么:
> 現在我們已經清楚,React的美妙和本質與瀏覽器或DOM無關,我們認為React的真正基礎是關于組件和元素的質樸想法:用聲明式的方式來描述任何你想渲染的東西。
在進入下一步之前,推薦你先觀看這個了不起的視頻[React in 7 Minutes](https://egghead.io/lessons/react-react-in-7-minutes),它的作者是John Lindquist,推薦你訂閱PRO以獲得更多的視頻教程。
另外,也可以考慮Udemy上的這個廣受好評的教程——[Build Web Apps with React JS and Flux](https://www.udemy.com/learn-and-understand-reactjs),作者是Stephen Grider。它包含超過71個視頻和10小時以上的內容,涵蓋了React,Flux,React Router,Firebase,Imgur API和其它。
當學習React時,我最大的挑戰是使用完全不同的思考方式去構建UI。這也是為什么你必須閱讀[Thinking in React](https://facebook.github.io/react/docs/thinking-in-react.html)([中文版](http://reactjs.cn/react/docs/thinking-in-react.html))這個官方指南的原因。
和Thinking in React中的產品列表風格類似,如果我們將*New Eden Faces*?UI分開為潛在的組件,它將會是這樣:

> 注意:每個組件都應該堅持單一職責原則,如果你發現你的組件做的事情太多,也許最好將它分成子組件。不過話雖如此,我首先還是編寫了一個典型的的單塊組件,當它能夠工作后,然后將它重構為小的子組件。
在我們的項目中,頂級App組件包含Navbar,Homepage和Footer組件,Homepage組件包含兩個Character組件。
所以,無論何時你想到一個UI設計,從將它分解為不同的組件開始,并且永遠考慮你的數據如何在父-子、子-父以及同胞組件間傳遞,否則你會遇到這樣的時刻:“WTF,這個到底在React里怎么實現的?這個用jQuery實現起來簡單多了……”
所以,下次你決定用React構建一個新app時,在寫代碼之前,先畫一個這樣的層次大綱圖。它幫你視覺化多個組件間的關系,并可以照著它來構建組件。
React中所有的組件都有`render()`方法,它總是返回一個單一的子元素。因此,下面的返回語句是錯誤的,因為它返回了3個子元素。
~~~
render() {
// Invalid JSX,
return (
<li>Achura</li>
<li>Civire</li>
<li>Deteis</li>
);
}
~~~
上面的HTML標記叫做[JSX](https://facebook.github.io/react/docs/jsx-in-depth.html)。它的語法和HTML僅有些微的不同,比如用`className`代替`class`,在我們開始開發應用的時候你將會學到它的更多內容。
當我第一眼看到這樣的語法,我的第一反應就是拒絕,在JavaScript中我習慣返回布爾值、數字、字符串、對象以及函數,但絕不是這種東西。但是,JSX不過是一個語法糖。使用一個`<ul>`標簽包裹上面的返回內容后,下面是不使用JSX時的模樣:
~~~
render() {
return React.createElement('ul', null,
React.createElement('li', null, 'Achura'),
React.createElement('li', null, 'Civire'),
React.createElement('li', null, 'Deteis')
);
}
~~~
我相信你會同意JSX遠比普通的JavaScript的可讀性更好,另外,[Babel](http://babeljs.io/)對JSX有內建支持,所以我們無需做任何額外的事情即可解析它。如果你用過AngularJS中的指令(directive)那么你將會欣賞React的做法,這樣你就不必同時處理兩個文件——*directive.js*(負責邏輯)和*template.html*(負責展現),你可以在同一個文件里同時處理邏輯和展現了。
React中的`componentDidMount`方法和jQuery中的`$(document).ready`非常相似,這個方法僅在組件第一次渲染后運行一次(只在客戶端運行),這里經常用于初始化第三方庫和jQuery插件,或者連接到Socket.IO。
在`render`方法中,你將經常使用三元運算符:當數據為空時隱藏元素、根據條件注入CSS類名、根據組件的狀態切換元素的展示等等。
比如下面的例子展示如果根據props值作為條件將CSS類名設為text-danger或text-success:
~~~
render() {
let delta = this.props.delta ? (
<strong className={this.props.delta > 0 ? 'text-success' : 'text-danger'}>
{this.props.delta}
</strong>
) : null;
return (
<div className='card'>
{delta}
{this.props.title}
</div>
);
}
~~~
這里我們僅僅淺嘗輒止了React的內容,但這應該已經足以展示React的一般概念和它的優點了。
React本身是非常簡單并且容易掌握的,但是,當我們談起Flux架構時,可能會有些麻煩。
- 前言
- 概述
- 第一步:新建Express項目
- 第二步:構建系統
- 第三步:項目結構
- 第四步: ES6速成教程
- 第五步: React速成教程
- 第六步:Flux架構速成教程
- 第七步:React路由(客戶端)
- 第八步:React路由(服務端)
- 第九步:Footer和Navbar組件
- 第十步:Socke.IO – 實時用戶數
- 第十一步:添加Character的組件
- 第十二步:數據庫模式
- 第十三步:Express API 路由(1/2)
- 第十五步:Home組件
- 第十四步:Express API 路由(2/2)
- 第十六步:角色(資料)組件
- 第十七步:Top 100 組件
- 第十八步:Stats組件
- 第十九步:部署
- 第二十步: 附加資源
- 總結