Reactjs 踏坑指南1: 知識點
- 什麼是React
- 虛擬DOM
- JSX
- 元件
- 生命週期和狀態
- 事件
- 單項資料流
- Reactjs和Angularjs的對比
React簡介
React是一個Facebook開發的UI庫。使用這個庫可以很方便的開發互動式的、具有表達力的和可重用的UI元件。本身並不是一個框架,可視為是檢視層,並且是一個以元件為基礎的高效檢視。對於React應用而言,你需要分割你的頁面,使其成為一個個的元件。也就是說你的應用是由一個個元件構成的。這種分割、複用元件的方式開發頁面,我們稱之為元件驅動開發。
這個庫還使用了一種叫做虛擬DOM(Virtual DOM)的概念,這些DOM可以根據狀態有選擇的渲染。這樣,頁面就會盡量的減少DOM操作而達到保持頁面狀態的效果。
虛擬DOM
用於優化檢視的渲染和重新整理。以前我們更新檢視時,需要先清空DOM容器中的內容,然後將最新的DOM和資料追加到容器中,現在React將這一操作放到了記憶體中。
詳細說明一下:
虛擬 DOM 是在 DOM 的基礎上建立了一個抽象層,我們對資料和狀態所做的任何改動,都會被自動且高效的同步到虛擬 DOM,最後再批量同步到 DOM 中。
React 會在記憶體中維護一個虛擬 DOM 樹,當我們對這個樹進行讀或寫的時候,實際上是對虛擬 DOM 進行的。當資料變化時,然後 React 會自動更新虛擬 DOM,然後拿新的虛擬 DOM 和舊的虛擬 DOM 進行對比,找到有變更的部分,得出一個Patch,然後將這個 Patch 放到一個佇列裡,最終批量更新這些 Patch 到 DOM 中。
這樣的機制可以保證即便是根節點資料的變化,最終表現在 DOM 上的修改也只是受這個資料影響的部分,可以保證非常高效的渲染。
因為React使用了虛擬DOM,因此藉助這種方式使得在服務端渲染輸出HTML成為可能。
JSX
JSX在ECMAScript的基礎上提供了類似於XML的擴充套件。
元件
使用ReactDOM的render方法的時候,第一個引數是需要渲染的我們建立的元件,第二個是HTML的DOM節點,元件渲染之後在這裡新增。我們可以使用createClass方法建立元件。
var MyComponent = React.createClass({
render: function(){
return (
<h1>Hello, world!</h1>
);
}
});
複製程式碼
注意:
- 類名一定要首字母大寫
- 新增元件屬性時,如果要使用class屬性和for屬性,屬性名不能直接用class和for,因為他們兩個是javascript的關鍵字,用className和htmlFor代替
元件建立好之後就可以在文件裡渲染出來了:
ReactDOM.render(
<MyComponent />,
document.getElementById('mount-point')
);
複製程式碼
建立元件的時候,可以給元件新增一些屬性,這些屬性都存在於props中。這些屬性可以通過this.props在元件內訪問,也可以在render方法渲染時使用。
var MyComponent = React.createClass({
render: function(){
return (
<h1>Hello, {this.props.name}!</h1>
);
}
});
ReactDOM.render(
<MyComponent name="handsome" />,
document.getElementById('mount-point')
);
複製程式碼
生命週期和狀態
生命週期
- componentWillMount 在渲染之前呼叫一次。
- componentDidMount 在渲染之後呼叫一次。
- shouldComponentUpdate 返回值決定元件是否需要update。
- componentWillUnmount 在解除安裝元件之前呼叫。
狀態
- getInitialState 返回State的初始值。
- getDefaultProps 獲取props的初始值。
- mixins 一組物件,主要用來擴充套件當前元件的功能。
每一個元件都包含一個state物件和一個props物件。State(狀態)用setState方法設定。呼叫setState方法會觸發UI的更新,也是實現互動式開發的必要基礎。如果我們要在一開始設定初始狀態(initial state),可以呼叫getInitialState方法。
state用來在建立元件的時候設定屬性,props用於渲染的時候生成想元件繫結屬性?
var MyComponent = React.createClass({
getInitialState:function(){
return {
count: 5
};
},
render: function(){
return (
<h1>Hello, {this.state.count}!</h1>
);
}
});
複製程式碼
事件
作為屬性包含在元件中
var Counter = React.createClass({
incrementCount: function(){
this.setState({
count: this.state.count + 1
});
},
getInitialState: function(){
return {
count: 0
}
},
render: function(){
return (
<div class="my-component">
<h1>Count: {this.state.count}</h1>
<button type="button" onClick={this.incrementCount}>Increment</button>
</div>
);
}
});
ReactDOM.render(
<Counter />,
document.getElementById('mount-point')
);
複製程式碼
單向資料流
在jquery時代,我們都是基於事件驅動,對於簡單的互動需求而言,這確實足夠了,而且開發起來非常迅速。但業務一旦複雜,這種基於事件驅動的東西就會變得很亂,頁面需要更新的DOM很多,就容易出錯。
單向資料流的概念就出現了。更新 DOM 的資料總是從頂層流下來,使用者事件不直接操作 DOM,而是操作頂層資料。這些資料從頂層流下來同時更新了DOM。你的程式碼就很少會直接處理DOM,而是隻處理資料的變更。這樣會很大程度上簡化程式碼和邏輯。
舉個例子:我點選一個button,然後頁面上一個span裡數字+1,原有的思考邏輯是“點選發生,然後資料變化,然後UI跟著變化+1”。而現在的思考邏輯是我的資料變化了,那麼我的UI會自動更新,那麼我只用考慮“點選發生,資料變化”。甚至可以把UI和資料變化分層然後處理。
具體地說:
在一個多元件結構裡,一個父元件需要負責管理狀態,並把資料通過props向下發放。
元件的狀態通過setState方法更新。資料通過設定子元件的屬性來傳遞給子元件,子元件通過this.props來獲取這些資料
例子1: 實現一個動態查詢框
var FilteredList = React.createClass({
filterList: function(event){
var updatedList = this.state.initialItems;
updatedList = updatedList.filter(function(item){
return item.toLowerCase().search(
event.target.value.toLowerCase()) !== -1;
});
this.setState({items: updatedList});
},
getInitialState: function(){
return {
initialItems: [
"Apples",
"Broccoli",
"Chicken",
"Duck",
"Eggs",
"Fish",
"Granola",
"Hash Browns"
],
items: []
}
},
componentWillMount: function(){
this.setState({items: this.state.initialItems})
},
render: function(){
return (
<div className="filter-list">
<input type="text" placeholder="Search" onChange={this.filterList}/>
<List items={this.state.items}/>
</div>
);
}
});
var List = React.createClass({
render: function(){
return (
<ul>
{
this.props.items.map(function(item) {
return <li key={item}>{item}</li>
})
}
</ul>
)
}
});
ReactDOM.render(<FilteredList/>, document.getElementById('mount-point'));
複製程式碼
React和Angular的對比
Angular是框架,React是類庫。ng是一個完整的框架,提供了比 React 多得多的建議和功能,你只需要直接使用就可以了。而要用React,開發者通常還需要藉助別的類庫來打造一個真正的應用。比如你可能需要react-router庫來處理路由、redux或flux管理state、額外的庫做測試以及管理依賴等等。 "如果僅從框架這一點來看,選擇Angular還是React就像選擇直接購買成品電腦還是買零件自己組裝一樣。"
在大小方面,由於ng是一個大而全的框架,自帶了更多的功能。而React只載入你需要的部件,react要比ng小得多。很多應用其實用不到這種大型框架提供的所有功能。在這個越來越擁抱微服務、微應用、單一職責模組(single-responsibility packages)的時代,React 通過讓你自己挑選必要模組,讓你的應用大小真正做到量身定做。
React以JavaScript為中心,把"HTML"放到JS裡,JavaScript遠比HTML要強大。因此,增強JavaScript讓其支援標籤要比增強HTML讓其支援邏輯要合理得多。無論如何,HTML與JavaScript 都需要某種方式以粘合在一起。 Angular是以HTML而非JavaScrip為中心的,把“JS”放到HTML裡。你必須學習學一大堆Angular特有的語法(標籤),即ng框架特有的HTML補丁(shim),比如為HTML加入了迴圈語義的HTML特性。而React只需要你懂JS。