React(二)原理

三 React主要原理

     Reactjs一個用來構建用戶界面的JavaScript庫,相當於MVC架構中的V層框架,與市面上其他框架不同的,React把每個組件當成了一個狀態機,組件內部通過state來維護組件狀態的變化,當組件的狀態發生變化時,React通過虛擬DOM技術來增量並高效的更新真實的DOM。

1.虛擬DOM (Virtual DOM)

       在前端開發的過程中,我們經常會做的一件事就是將變化的數據實時的更新到UI上,這時就需要對DOM進行更新和重新渲染,而頻繁的DOM操作通常是性能瓶頸產生的原因之一,有時候我們會遇到這樣一種尷尬的情況:比如有一個列表數據,當用戶執行刷新操作時,Ajax會重新從後臺請求數據,即使新請求的數據和上次完全相同,DOM也會被全部更新一遍並進行渲染,這樣就產生不必要的開銷。

       React爲此引入了虛擬DOM(Virtual DOM)機制,對於每個組件,React會在內存中構建一個相對應的DOM樹,基於React開發時所有的DOM結構都是通過虛擬DOM進行,每當組件的狀態發生變化時,React都會重新構建整個DOM數據,然後將當前的整個DOM樹和上一次的DOM樹進行對比,得出DOM結構變化的部分(Patchs),然後將這些Patchs在更新到真實的DOM中。整個過程都是在內存中進行。因此是非常高效的。


2.React 生命週期

  React把每個組件都當作一個狀態機來維護和管理,因此每個組件都擁有一套完整的生命週期,大致可以分爲三個過程:初始化、更新和銷燬。生命週期的每一個過程都明確的反映了組件的狀態變化。對於開發來說就能很容易的把握件的每個狀態,不同的狀態時期做對應的事情,互不干擾。以下是和組件生命週期相關的幾個方法:

1
2
3
4
5
6
7
8
9
getDefaultProps //創建組建
getInitialState  //實例化狀態
componentWillMount  //掛載前
componentDidMount //掛載後
componentWillReceiveProps //屬性被改變時
shouldComponentUpdate //是否更新
componentWillUpdate //更新前
componentDidUpdate //更新後
componentWillUnmount //銷燬前

3.初始化

        對於外部系統來說,組件是一個獨立存在的封閉系統,內部的邏輯被隱藏,只對外暴露傳遞數據的接口,而React爲我們提供了兩種方式來向組件傳遞數據,即props和state。

       props是在調用ReactDOM.render()時通過標籤屬性xxx傳遞,然後通過this.props.xxx來獲取,getDefaultProps 允許你爲組件設置一個默認的props值,在沒有傳遞props的情況下顯示的是默認值。

querySelector() 方法返回匹配指定 CSS 選擇器元素的第一個子元素 。 該方法只返回匹配指定選擇器的第一個元素。如果要返回所有匹配元素,需要使用 querySelectorAll() 方法替代.

由於querySelector是按css規範來實現的,所以它傳入的字符串中第一個字符不能是數字.

query選擇符選出來的元素及元素數組是靜態的,而getElement這種方法選出的元素是動態的。靜態的就是說選出的所有元素的數組,不會隨着文檔操作而改變.
在使用的時候getElement這種方法性能比較好,query選擇符則比較方便.


// 創建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的值設置爲真實數據。

var HelloReact = React.createClass({
/**
* 設置組件的初始值
* @returns {{data: Array, msg: string}}
*/
getInitialState:function(){
return{
data:"數據加載中..." //初識值爲[]
}
},
/**
* 掛載後首次加載數據
*/
componentDidMount:function(){
this
},
requestData:function(){
$.ajax({
url:'xxx.ashs',
data:{},
success:function(data){
this.setState({
data: data//通過setState()更新服務器數據
})
}
}.bind(data))
},
render:function(){
return(
<div>
{this.state.data}
</div>
)
}
});

4.更新

        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的時間。

5. 銷燬

      當組件從DOM中被移除時,React會銷燬之。在銷燬之前,細心的React還觸發 componentWillUnmount 來通知你,看你最後有沒有什麼話想對這個即將銷燬的組件說,當然你沒什麼事就不用了。


6.props 和state

         我們已經知道可以通過props和state兩種方式向組件傳遞數據,props是隻讀的不能被改變,而 state 是用來反映一個組件的狀態,是可以改變的。因此,當組件所需要的數據在調用時是已經確定的,不頻繁發生變化的,就可以使用props來傳遞,相反,當組件所需要的數據在調用時不能確定,需要等待異步回調時才能確定,比如ajax請求數據,input的onchange事件,這時就需要使用state來記錄和改變這些值得變化。




















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章