怎樣用React JS構建一個用戶界面?本文將快速地給你一個React JS的概覽。代碼,請君移步react-starter
概念
React只有很少的API,這使得它很容易去學習與理解。當然,使用它也是相當有意思的。但是,簡約卻並不簡單。在我們開始之前,有一些概念是需要去理解的。
React元素(React elements)
React元素是用於呈現HTML結構的JavaScript對象。它們不會存在於瀏覽器中,只是用於描述瀏覽器中的元素,比如h1
, div
或者 section
等等。
模塊(Components)
模塊是開發者創建的React元素。它們通過比用戶界面的范圍要大,因為它們同時包含了其結構與功能。想像一下導航欄,點贊按鈕,圖片上傳這些模塊的概念。
JSX
JSX是一種用於創建React元素和模塊的技術,或者說是規范、語言。比如 <h1>Hello</h1>
便是一個用JSX所寫的React元素。同樣的React元素,可以用原生的JavaScript實現,即 React.DOM.h1(null, 'Hello');
。相比原生的JavaScript,JSX更加簡潔。會讓你花更少的精力去讀和寫代碼,在上線的時候將其轉換成原生的JavaScript即可。
虛擬DOM(Virtual DOM)
虛擬DOM是一個JavaScript的樹形結構,包含了React元素和模塊。React通過渲染虛擬DOM到瀏覽器,使得用戶界面得以顯示。React也會觀察虛擬DOM的變化,根據虛擬DOM自動地改變瀏覽器DOM元素。
了解了這些概念之后,我們就可以暢快地敲React代碼了。這里將會創建一系列的用戶界面,每一個界面都將提前添加一層功能層。我們會做一個類似instagram的應用 - 當然,這個很粗糙。
渲染(Rendering)
業務的第一步是渲染一個虛擬的元素(React元素或者模塊都可以)。由於每一個虛擬元素都存在於內存之中,所以我們必須顯式地告訴React,將其渲染到瀏覽器的DOM之中。
React.render(<img src='http://owenyang0.github.io/img/background.jpg' />, document.body);
render
函數接受兩個參數,一個是虛擬元素,一個是真實的DOM節點。React就是獲取到虛擬元素之后,將其插入到所給的節點之中。此時,在瀏覽器中便可以看到照片了。
模塊(Components)
模塊是React的核心與靈魂。它們可以自定義React元素。經常由單一的功能或者結構擴展而來。
var Photo = React.createClass({
render: function() {
return <img src='http://owenyang0.github.io/img/background.jpg' />
}
});
React.render(<Photo />, document.body);
createClass
函數接受一個對象,該對象實現了render
的函數。
這個Photo
模塊被構建好,<Photo />
,然后渲染到document body中。
該模塊並沒有比上一個React圖像元素做更多的事情,但這卻更加有利於在功能和結構上進行擴展。
屬性(Props)
屬性可以認為是模塊的一些配置選項。它們以參數(arguments)的形式傳遞給模塊,看起來就像HTML的屬性(attributes)。
var Photo = React.createClass({
render: function() {
return (
<div className='photo'>
<img src={this.props.imageURL} />
<span>{this.props.caption}</span>
</div>
)
}
});
React.render(<Photo imageURL='http://owenyang0.github.io/img/background.jpg' caption='Headset' />, document.body);
在render
函數里面,兩個屬性(props)傳到了Photo
模塊,imageURL
和 caption
。imageURL
屬性被用作React元素中的src
。而caption
屬性則以純文本的方式在React中的span元素使用。
值得一提的是,模塊永遠不應該去改變屬性的的值,它們是不可變的。如果一個模塊有一個可變的數據,那應該應用使用狀態對象(state object)。
狀態(State)
狀態對象是一個模塊的內部對象。它會持有可變的數據。
var Photo = React.createClass({
toggleLiked: function() {
this.setState({
liked: !this.state.liked
});
},
getInitialState: function() {
return {
liked: false
}
},
render: function() {
var buttonClass = this.state.liked ? 'active' : '';
return (
<div className='photo'>
<img src={this.props.src} />
<div className='bar'>
<button onClick={this.toggleLiked} className={buttonClass}>
♥
</button>
<span>{this.props.caption}</span>
</div>
</div>
)
}
});
React.render(<Photo src='http://owenyang0.github.io/img/background.jpg' caption='Headset'/>, document.body);
在模塊中引入狀態,會增加一點點的復雜度。
在這模塊中,有一個新的函數getInitialState
。當模塊初始化的時候,React會調用這個函數。而返回的對象則作為React的初始化狀態(看函數名就知道)。
還有一個新的函數叫toggleLiked
。這個函數調用了模塊上的setState方法,可以改變狀態liked
的值。
通過模塊的render函數,變量buttonClass
被賦值成了'active'或者空,這都依賴於liked
狀態。
buttonClass
是React按鈕元素的class名字。按鈕還擁有一個onClick
的事件回調,指向toggleLiked
函數。
當模塊渲染成瀏覽器DOM的時候,究竟發生全過程:
- 當按鈕點擊被觸發時,調用了
toggleLiked
liked
的狀態被改變- React將模塊再次渲染成虛擬DOM
- 新的虛擬DOM與舊的虛擬DOM相比較
- React將改變的部分隔離,然后更新到瀏覽器DOM
在這個場景中,React會改變button上的類名。
組合(Composition)
組合的意思是說,將小的分散的模塊組成一個大的整體。比如Photo
模塊可以在PhotoGallery
中使用:
var Photo = React.createClass({
toggleLiked: function() {
this.setState({
liked: !this.state.liked
});
},
getInitialState: function() {
return {
liked: false
}
},
render: function() {
var buttonClass = this.state.liked ? 'active' : '';
return (
<div className='photo'>
<img src={this.props.src} />
<div className='bar'>
<button onClick={this.toggleLiked} className={buttonClass}>
♥
</button>
<span>{this.props.caption}</span>
</div>
</div>
)
}
});
var PhotoGallery = React.createClass({
getDataFromServer: function() {
return [{
url: 'http://owenyang0.github.io/img/background.jpg',
caption: 'Headset'
},
{
url: 'http://owenyang0.github.io/images/mocha.png',
caption: 'Mocha'
},
{
url: 'http://owenyang0.github.io/images/catalog.png',
caption: 'Catelog'
}];
},
render: function() {
var data = this.getDataFromServer();
var photos = data.map(function(photo) {
return <Photo src={photo.url} caption={photo.caption} />
});
return (
<div className='photo-gallery'>
{photos}
</div>
)
}
});
React.render(<PhotoGallery />, document.body);
這個Photo
模塊完完全全和上面的一樣。但新的PhotoGallery
模塊會生成Photo
模塊。該場景中,偽造了返回包含三個對象的數組的數據,每一個對象都返回一個url和其標題。通過循環,生成了三個Photo
的模塊,將最終的返回值插入到render
函數之中。
小結
用React來構建你的用戶界面,我想這也差不多了。React的文檔手冊,包含了所有的細節。強烈推薦大家去讀一下。
同樣的,該文也沒有涉及你本地環境安裝的細節。文檔都會有的。