Reactjs 踏坑指南1: 知識點
- 什么是React
- 虛擬DOM
- JSX
- 組件
- 生命周期和狀態
- 事件
- 單項數據流
- Reactjs和Angularjs的對比
React簡介
React是一個Facebook開發的UI庫。使用這個庫可以很方便的開發交互式的、具有表達力的和可重用的UI組件。本身并不是一個框架,可視為是視圖層,并且是一個以組件為基礎的高效視圖。對于React應用而言,你需要分割你的頁面,使其成為一個個的組件。也就是說你的應用是由一個個組件構成的。這種分割、復用組件的方式開發頁面,我們稱之為組件驅動開發。
這個庫還使用了一種叫做虛擬DOM(Virtual DOM)的概念,這些DOM可以根據狀態有選擇的渲染。這樣,頁面就會盡量的減少DOM操作而達到保持頁面狀態的效果。
- React JSFiddle 在線編輯工具
- React 入門示例
虛擬DOM
用于優化視圖的渲染和刷新。以前我們更新視圖時,需要先清空DOM容器中的內容,然后將最新的DOM和數據追加到容器中,現在React將這一操作放到了內存中。
詳細說明一下:
虛擬 DOM 是在 DOM 的基礎上建立了一個抽象層,我們對數據和狀態所做的任何改動,都會被自動且高效的同步到虛擬 DOM,最后再批量同步到 DOM 中。
React 會在內存中維護一個虛擬 DOM 樹,當我們對這個樹進行讀或寫的時候,實際上是對虛擬 DOM 進行的。當數據變化時,然后 React 會自動更新虛擬 DOM,然后拿新的虛擬 DOM 和舊的虛擬 DOM 進行對比,找到有變更的部分,得出一個Patch,然后將這個 Patch 放到一個隊列里,最終批量更新這些 Patch 到 DOM 中。
這樣的機制可以保證即便是根節點數據的變化,最終表現在 DOM 上的修改也只是受這個數據影響的部分,可以保證非常高效的渲染。
- 關于虛擬DOM diff算法的詳細分析
因為React使用了虛擬DOM,因此借助這種方式使得在服務端渲染輸出HTML成為可能。
JSX
JSX在ECMAScript的基礎上提供了類似于XML的擴展。
- JSX in depth
組件
使用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。