標籤:

React 的數據載體:state、props、context

一、state

描述:內部狀態(local state)或者局部狀態;

初始化內部狀態:React構造函數中

更新內部狀態:this.setstate

獲取內部狀態:this.state

export default class Counter extends Component{ntconstructor(){nttsuper(); //後才能用this獲取實例化對象nttthis.state{ntttvalue: 0ntt};nt}nntrender(){nttreturn(nttt<div>ntttt<button onClick = { () => this.setState({valuethis.state.value+1})}>ntttttINCREMENTntttt</button>nttttCounter組件的內部狀態ntttt<pre>JSON.stringify(this.state.value, null, 2)</pre>nttt</div>nttt);nt}n}n

二、Props

可以使用它向組件傳遞數據,React組件從props拿到數據,然後返回視圖;

1、使用props

向一個組件傳遞數據的方法是將數據寫在組件的標籤中;

<Content value = {this.state.value}/>n

組件如何獲取props呢?無狀態函數編寫的組件中獲取props屬性非常簡單;

function Content(props){ntreturn(nttt<p>Content組件的props.value: {props.value}</p>ntt);n}n

在使用類編寫組件的時候,需通過this.props獲取props,this是組件的實例

三、組合使用state與props

思路:通過Counter組件更新state.value,然後將更新的state.value通過props傳遞給Content組件

import React, {Component, ProTypes} from react;nnfunction Content(props){ntreturn <p>Content組件的props.value: {props.value}</p>;n}nnContent.ProTypes = {ntvalue: ProTypes.number.isRequiredn};nnexport default Counter extends Component{ntconstructor(){nttsuper();nttthis.state{ntttvalue: 0ntt}nt}nntrender(){nttreturn(nttt<div>ntttt<button onClick= {() => {this.setstate({value: this.state.value+1})}}ntttttINCREMENTntttt</button>ntttttCounter組件的內部狀態:ntttt<pre>JSON.stringify(this.state.value, null, 2)</pre>ntttt<Content value = {this.state.value}/>nttt</div>nttt);nt}n}n

四、Context

組件間跨級傳遞數據

Context 與props傳遞數據的對比

1、使用props傳遞數據

編寫三個組件:按鈕(Button)、消息(Message)、消息列表(MessageList)

在最外層的消息列表組件中定義一個變數color,然後通過props將color傳遞給內層按鈕組件;

父組件——>子組件

import React, {ProTypes} from react;nnfunction Button(props){ntreturn(nttt<button style = {{background: props.color}}>ntttt{props.children} //把所有子元素(子組件)顯示出來,這裡是Deletenttt</button>ntt);n}nnButton.proTypes = {ntcolor: ProTypes.string.isRequired,ntchildren: ProTypes.string.isRequiredn}nnfunction Message(props){ntreturn(nttt<li>nttt props.text<Button color = {props.color}>Delete</Button>nttt</li>ntt);n}nnMessage.proTypes = {ntcolor: ProTypes.string.isRequired,nttext: ProTypes.string.isRequiredn}nnfunction MessageList(){ntconst color = red;ntconst messages = [ntt{text: hello React},ntt{text: hello Redux}nt];nntconst children = messages.map((message, key) => nttt<Message key = {key} text = {message.text} color = {color}/>ntt);nntreturn(ntt<div>nttt<p>通過props將color逐層傳遞給自子組件Button</p>nttt<ul>ntttt{children}nttt</ul>ntt</div>ntt);n}nnexport default MessageList;n

注意:1)、在MessageList組件中遍歷生成Message組件,並向其傳遞了key text color等props,雖然key這個props沒有用到,但是當你遍歷生成一個組件列表的時候,仍然要給列表中的每一項傳遞key。這是因為React的DIFF演算法需要key來做重新排列,以高效的更新DOM;

2)、消息組件中沒有子元素,要寫自閉形式;

3)、在消息組件中,渲染按鈕組件,並向其傳遞了color;

4)、在按鈕組件中,渲染了一個普通按鈕,並聲明式的定義了它的背景顏色為上級組件傳遞來的color;

2、使用context傳遞數據

1)將要傳遞的數據放在消息列表組件的context中;

2)在按鈕組件中聲明contextTypes,就可以通過組件實例的context屬性訪問到數據了;

import React, {Component, ProTypes} from react;nnfunction Button(props, context){ntreturn(nttt<button style = {{background: context.color}}>ntttt{props.children}nttt</button>ntt);n}nnButton.proTypes = {ntcolor: ProTypes.string.isRequired,ntchildren: ProTypes.string.isRequiredn};nnButton.contextTypes = {ntcolor: ProTypes.string.isRequiredn};nnfunction Message(props){ntreturn(nttt<li>nttttprops.text<Button Delete></Button>nttt</li>ntt);n}nnMessage.proTypes = {nttext: ProTypes.string.isRequiredn};nnclass MessageList extends Component{ntgetChildContext(){nttreturn {color: red};nt}nntrender(){nttconst messages = [nttt{text: hello React},nttt{text: hello Redux}ntt];nnttconst children = messages.map((message, key) =>ntttt<Message key = {key} text = {message.text}/>nttt);nnttreturn(ntttt<div>nttttt<p>通過context將color跨級傳遞給裡面的Button組件</p>nttttt<ul>ntttttt{children}nttttt</ul>ntttt</div>nttt);nt}n}nnMessageList.childContextTypes = {ntcolor: ProTypes.string.isRequired;n}nnexport default MessageList;n

注意:1)在消息列表組件中遍歷生成消息組件,並向其傳遞key和text這兩個props。然後通過getChildContext方法將color放在context中,並聲明了childrenContextTypes。如果不聲明的話,將無法在組件中使用getChildContext()方法;

2)在消息組件中,渲染按鈕組件,就不用再直接傳遞color了;

3)在按鈕組件中,首選傳遞父組件的props和全局的context,然後渲染一個普通的按鈕,並聲明式的定義它的背景顏色為context.color。如果沒定義contextTypes,context將會是空對象;

另外,無狀態組件可以直接在函數參數中獲取context,而又狀態組件可以通過this.context和生命周期函數獲取context;

3、使用場景

React的context和全局變數相似,應避免使用,場景包括:傳遞登錄信息、當前語音以及主題信息;

如果只傳遞一些功能模塊數據,則盡量不要使用context,使用props傳遞數據會更加清晰;

使用context會使組件的復用性降低,因為這些組件依賴上下文,當你在別的地方渲染的時候,可能會出現差異;

五、React開發者工具中查看

chrome插件:React Developer Tools

六、總結

1、state稱為內部狀態或者局部狀態,內部狀態的操作配合React事件系統,可以實現用戶交互的功能

2、Props與context則用於在組件間傳遞數據。使用props傳遞數據簡單清晰,但是跨級傳遞非常麻煩。使用

context可以跨級傳遞數據,但是會降低組件的復用性,因為這些組件依賴「上下文」,。所有盡量只使用context傳遞登錄狀態、顏色主題等全局數據。

3、在React開發者工具中,可以清晰地看到每個組件的state、props以及context等信息,便於開發和調試。


推薦閱讀:

如何用React做一個MVC項目?
setState的函數參數叫啥名好
怎樣看待民工叔去螞蟻金服?

TAG:React |