React 起源於 Facebook 內部項目,是一個用來構建用戶界面的 Javascript 庫,至關於MVC架構中的V層框架,與市面上其餘框架不一樣的是,React 把每個組件當成了一個狀態機,組件內部經過 state 來維護組件狀態的變化,當組件的狀態發生變化時,React 經過虛擬DOM技術來增量而且高效的更新真實DOM。本文將對React 的這些特色進行簡單的介紹。html
考慮到有的同窗還未曾瞭解過 React,咱們先來寫一個簡單的 React 組件,讓你們一睹爲快!前端
// 建立一個HelloReact組件 var HelloReact = React.createClass({ render:function(){ return ( <div> Hello React! </div> ) } }); // 使用HelloReact組件 ReactDOM.render( <HelloReact />, document.querySelector('body') )
這樣就定義了一個React組件,固然要運行這段代碼是有條件的,須要引入React庫,還須要引入JSX語法轉換庫,這裏很少說了,這些基礎的東西還須要各位親自實踐纔好!ajax
在前端開發的過程當中,咱們常常會作的一件事就是將變化的數據實時更新到UI上,這時就須要對DOM進行更新和從新渲染,而頻繁的DOM操做一般是性能瓶頸產生的緣由之一,有時候咱們會遇到這樣一種尷尬的狀況:好比有一個列表數據,當用戶執行刷新操做時,Ajax會從新從後臺請求數據,即便新請求的數據和上次徹底相同,DOM也會被所有更新一遍並進行從新渲染,這樣就產生了沒必要要的性能開銷。服務器
React爲此引入了虛擬DOM(Virtual DOM)機制:對於每個組件,React會在內存中構建一個相對應的DOM樹,基於React開發時全部的DOM構造都是經過虛擬DOM進行,每當組件的狀態發生變化時,React都會從新構建整個DOM數據,而後將當前的整個DOM樹和上一次的DOM樹進行對比,得出DOM結構變化的部分(Patchs),而後將這些Patchs 再更新到真實DOM中。整個過程都是在內存中進行,所以是很是高效的。借用一張圖能夠清晰的表示虛擬DOM的工做機制:架構
React 把每一個組件都看成一個狀態機來維護和管理,所以每一個組件都擁有一套完整的生命週期,大體能夠分爲三個過程:初始化、更新和銷燬。生命週期的每個過程都明確的反映了組件的狀態變化。對於開發來講就能很容易的把握組件的每一個狀態,不一樣的狀態時期作對應的事情,互不干擾。如下是和組件生命週期相關的幾個方法:框架
getDefaultProps異步
getInitialState性能
componentWillMountthis
componentDidMounturl
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
對於外部系統來講,組件是一個獨立存在的封閉系統,內部的邏輯被隱藏,只對外暴露傳遞數據的接口,而React爲咱們提供了兩種方式來向組件傳遞數據,即 props 和 state。
props 是在調用 ReactDOM.render() 時經過標籤屬性xxx傳遞,而後經過 this.props.xxx 來獲取,getDefaultProps 容許你爲組件設置一個默認的props值,在沒有傳遞props的狀況下顯示默認值。
// 建立HelloReact組件 var HelloReact = React.createClass({ /** * 當設置props的默認值 當沒有傳遞時顯示默認值 * @return {} */ getDefaultProps:function(){ return { data:"暫無數據" } }, render:function(){ return ( <div> //顯示data,當props發生變化時會自動更新 {this.props.data} </div> ) } });//傳遞props屬性data ReactDOM.render( <HelloReact data={"Hello React!"} />, document.querySelector('body') )
和 props 不一樣的是,state不能經過外部傳遞,所以在使用state以前,須要在 getInitialState 中爲state設置一個默認值,而後才能經過 this.state.xxx 來訪問,當組件被掛載完成時,觸發 componentDidMount 方法,咱們能夠在這裏經過Ajax請求服務器數據,而後再經過 setState() 把state的值設置爲真實數據。
// 建立HelloReact組件 var HelloReact = React.createClass({ /** * 設置組件的初始值 * @returns {{data: Array, msg: string}} */ getInitialState:function(){ return { data:"數據加載中..." //初始值爲[] } }, /** * 掛載後首次加載數據 */ componentDidMount:function(){ this.requestData();//請求數據 }, /** * 請求後臺數據 */ requestData:function(){ $.ajax({ url:'xxxx.ashx', data:{}, success:function(data){ this.setState({ data:data //經過setState()更新服務器數據 }) } }.bind(this)) }, render:function(){ return ( <div> {this.state.data} </div> ) } }); ReactDOM.render( <HelloReact />, document.querySelector('body') )
props屬性是隻讀的,若是想要改變props的值,只能經過從新調用render()來傳遞新的props,但要注意的是,從新執行render()組件不會被從新掛載,而是經過虛擬DOM技術進行增量更新和渲染,這時還會觸發 componentWillReceiveProps 方法,並將新的props做爲參數傳遞,你能夠在這裏對新的props進行處理。
相比props,state天生就是用來反映組件狀態的,所以它的值是能夠被改變的,當state的值被改變時,經過setState就能夠改變state的值,React一樣也是採用虛擬DOM技術來計算須要被更新的部分,而不是牽一髮動全身的更新和渲染。
當 props 和 state 的狀態發生變化後,組件在即將更新以前還會觸發一個叫 shouldConponentUpdate 的方法,若是 shouldConponentUpdate 返回的是 true,無論props和state 的值和上一次相比有沒有變化,React 都會老老實實的進行對比。此時,若是你肯定以及確定兩次數據沒有變化,那就讓 shouldConponentUpdate 返回 false,React就不會進行diff了,更不會從新渲染了。瞬間省去了 diff 的時間。
當組件從DOM中被移除時,React會銷燬之。在銷燬以前,細心的React還觸發 componentWillUnmount 來通知你,看你最後有沒有什麼話想對這個即將銷燬的組件說,固然你沒什麼事就不用了。
咱們已經知道能夠經過 props 和 state 兩種方式向組件傳遞數據,props 是隻讀的不能被改變,而 state 是用來反映一個組件的狀態,是能夠改變的。所以,當組件所須要的數據在調用時是已經肯定的,不頻繁發生變化的,就可使用props來傳遞,相反,當組件所須要的數據在調用時不能肯定,須要等待異步回調時才能肯定,好比ajax請求數據,input 的 onchange事件,這時就須要使用state 來記錄和改變這些值得變化。
原創發佈 @一像素 2016