国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React 深入系列3:Props 和 State

endiat / 1926人閱讀

摘要:當(dāng)真正執(zhí)行狀態(tài)修改時(shí),依賴的并不能保證是最新的,因?yàn)闀?huì)把多次的修改合并成一次,這時(shí),還是等于這幾次修改發(fā)生前的。下篇預(yù)告深入系列組件的生命周期新書推薦進(jìn)階之路作者徐超畢業(yè)于浙江大學(xué),碩士,資深前端工程師,長期就職于能源物聯(lián)網(wǎng)公司遠(yuǎn)景智能。

文:徐超,《React進(jìn)階之路》作者

授權(quán)發(fā)布,轉(zhuǎn)載請注明作者及出處

React 深入系列3:Props 和 State
React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使用React。

React 的核心思想是組件化的思想,而React 組件的定義可以通過下面的公式描述:

UI = Component(props, state)

組件根據(jù)props和state兩個(gè)參數(shù),計(jì)算得到對應(yīng)界面的UI。可見,props 和 state 是組件的兩個(gè)重要數(shù)據(jù)源。

本篇文章不是對props 和state 基本用法的介紹,而是嘗試從更深層次解釋props 和 state,并且歸納使用它們時(shí)的注意事項(xiàng)。

Props 和 State 本質(zhì)

一句話概括,props 是組件對外的接口,state 是組件對內(nèi)的接口。組件內(nèi)可以引用其他組件,組件之間的引用形成了一個(gè)樹狀結(jié)構(gòu)(組件樹),如果下層組件需要使用上層組件的數(shù)據(jù)或方法,上層組件就可以通過下層組件的props屬性進(jìn)行傳遞,因此props是組件對外的接口。組件除了使用上層組件傳遞的數(shù)據(jù)外,自身也可能需要維護(hù)管理數(shù)據(jù),這就是組件對內(nèi)的接口state。根據(jù)對外接口props 和對內(nèi)接口state,組件計(jì)算出對應(yīng)界面的UI。

組件的props 和 state都和組件最終渲染出的UI直接相關(guān)。兩者的主要區(qū)別是:state是可變的,是組件內(nèi)部維護(hù)的一組用于反映組件UI變化的狀態(tài)集合;而props是組件的只讀屬性,組件內(nèi)部不能直接修改props,要想修改props,只能在該組件的上層組件中修改。在組件狀態(tài)上移的場景中,父組件正是通過子組件的props,傳遞給子組件其所需要的狀態(tài)。

如何定義State

定義一個(gè)合適的state,是正確創(chuàng)建組件的第一步。state必須能代表一個(gè)組件UI呈現(xiàn)的完整狀態(tài)集,即組件對應(yīng)UI的任何改變,都可以從state的變化中反映出來;同時(shí),state還必須是代表一個(gè)組件UI呈現(xiàn)的最小狀態(tài)集,即state中的所有狀態(tài)都是用于反映組件UI的變化,沒有任何多余的狀態(tài),也不需要通過其他狀態(tài)計(jì)算而來的中間狀態(tài)。

組件中用到的一個(gè)變量是不是應(yīng)該作為組件state,可以通過下面的4條依據(jù)進(jìn)行判斷:

這個(gè)變量是否是通過props從父組件中獲取?如果是,那么它不是一個(gè)狀態(tài)。

這個(gè)變量是否在組件的整個(gè)生命周期中都保持不變?如果是,那么它不是一個(gè)狀態(tài)。

這個(gè)變量是否可以通過state 或props 中的已有數(shù)據(jù)計(jì)算得到?如果是,那么它不是一個(gè)狀態(tài)。

這個(gè)變量是否在組件的render方法中使用?如果不是,那么它不是一個(gè)狀態(tài)。這種情況下,這個(gè)變量更適合定義為組件的一個(gè)普通屬性(除了props 和 state以外的組件屬性 ),例如組件中用到的定時(shí)器,就應(yīng)該直接定義為this.timer,而不是this.state.timer。

請務(wù)必牢記,并不是組件中用到的所有變量都是組件的狀態(tài)!當(dāng)存在多個(gè)組件共同依賴同一個(gè)狀態(tài)時(shí),一般的做法是狀態(tài)上移,將這個(gè)狀態(tài)放到這幾個(gè)組件的公共父組件中。

如何正確修改State 1.不能直接修改State。

直接修改state,組件并不會(huì)重新重發(fā)render。例如:

// 錯(cuò)誤
this.state.title = "React";

正確的修改方式是使用setState():

// 正確
this.setState({title: "React"});
2. State 的更新是異步的。

調(diào)用setState,組件的state并不會(huì)立即改變,setState只是把要修改的狀態(tài)放入一個(gè)隊(duì)列中,React會(huì)優(yōu)化真正的執(zhí)行時(shí)機(jī),并且React會(huì)出于性能原因,可能會(huì)將多次setState的狀態(tài)修改合并成一次狀態(tài)修改。所以不能依賴當(dāng)前的state,計(jì)算下個(gè)state。當(dāng)真正執(zhí)行狀態(tài)修改時(shí),依賴的this.state并不能保證是最新的state,因?yàn)镽eact會(huì)把多次state的修改合并成一次,這時(shí),this.state還是等于這幾次修改發(fā)生前的state。另外需要注意的是,同樣不能依賴當(dāng)前的props計(jì)算下個(gè)state,因?yàn)閜rops的更新也是異步的。

舉個(gè)例子,對于一個(gè)電商類應(yīng)用,在我們的購物車中,當(dāng)點(diǎn)擊一次購買按鈕,購買的數(shù)量就會(huì)加1,如果我們連續(xù)點(diǎn)擊了兩次按鈕,就會(huì)連續(xù)調(diào)用兩次this.setState({quantity: this.state.quantity + 1}),在React合并多次修改為一次的情況下,相當(dāng)于等價(jià)執(zhí)行了如下代碼:

Object.assign(
  previousState,
  {quantity: this.state.quantity + 1},
  {quantity: this.state.quantity + 1}
)

于是乎,后面的操作覆蓋掉了前面的操作,最終購買的數(shù)量只增加了1個(gè)。

如果你真的有這樣的需求,可以使用另一個(gè)接收一個(gè)函數(shù)作為參數(shù)的setState,這個(gè)函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是組件的前一個(gè)state(本次組件狀態(tài)修改成功前的state),第二個(gè)參數(shù)是組件當(dāng)前最新的props。如下所示:

// 正確
this.setState((preState, props) => ({
  counter: preState.quantity + 1; 
}))
3. State 的更新是一個(gè)淺合并(Shallow Merge)的過程。

當(dāng)調(diào)用setState修改組件狀態(tài)時(shí),只需要傳入發(fā)生改變的狀態(tài)變量,而不是組件完整的state,因?yàn)榻M件state的更新是一個(gè)淺合并(Shallow Merge)的過程。例如,一個(gè)組件的state為:

this.state = {
  title : "React",
  content : "React is an wonderful JS library!"
}

當(dāng)只需要修改狀態(tài)title時(shí),只需要將修改后的title傳給setState

this.setState({title: "Reactjs"});

React會(huì)合并新的title到原來的組件state中,同時(shí)保留原有的狀態(tài)content,合并后的state為:

{
  title : "Reactjs",
  content : "React is an wonderful JS library!"
}
State與Immutable

React官方建議把state當(dāng)作不可變對象,一方面是如果直接修改this.state,組件并不會(huì)重新render;另一方面state中包含的所有狀態(tài)都應(yīng)該是不可變對象。當(dāng)state中的某個(gè)狀態(tài)發(fā)生變化,我們應(yīng)該重新創(chuàng)建一個(gè)新狀態(tài),而不是直接修改原來的狀態(tài)。那么,當(dāng)狀態(tài)發(fā)生變化時(shí),如何創(chuàng)建新的狀態(tài)呢?根據(jù)狀態(tài)的類型,可以分成三種情況:

1. 狀態(tài)的類型是不可變類型(數(shù)字,字符串,布爾值,null, undefined)

這種情況最簡單,因?yàn)闋顟B(tài)是不可變類型,直接給要修改的狀態(tài)賦一個(gè)新值即可。如要修改count(數(shù)字類型)、title(字符串類型)、success(布爾類型)三個(gè)狀態(tài):

this.setState({
  count: 1,
  title: "Redux",
  success: true
})
2. 狀態(tài)的類型是數(shù)組

如有一個(gè)數(shù)組類型的狀態(tài)books,當(dāng)向books中增加一本書時(shí),使用數(shù)組的concat方法或ES6的數(shù)組擴(kuò)展語法(spread syntax):

// 方法一:使用preState、concat創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.concat(["React Guide"]);
}))

// 方法二:ES6 spread syntax
this.setState(preState => ({
  books: [...preState.books, "React Guide"];
}))

當(dāng)從books中截取部分元素作為新狀態(tài)時(shí),使用數(shù)組的slice方法:

// 使用preState、slice創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.slice(1,3);
}))

當(dāng)從books中過濾部分元素后,作為新狀態(tài)時(shí),使用數(shù)組的filter方法:

// 使用preState、filter創(chuàng)建新數(shù)組
this.setState(preState => ({
  books: preState.books.filter(item => {
    return item != "React"; 
  });
}))

注意不要使用push、pop、shift、unshift、splice等方法修改數(shù)組類型的狀態(tài),因?yàn)檫@些方法都是在原數(shù)組的基礎(chǔ)上修改,而concat、slice、filter會(huì)返回一個(gè)新的數(shù)組。

3. 狀態(tài)的類型是簡單對象(Plain Object)

如state中有一個(gè)狀態(tài)owner,結(jié)構(gòu)如下:

this.state = {
  owner = {
    name: "老干部",
    age: 30
  }  
}

當(dāng)修改state時(shí),有如下兩種方式:

1) 使用ES6 的Object.assgin方法

this.setState(preState => ({
  owner: Object.assign({}, preState.owner, {name: "Jason"});
}))

2) 使用對象擴(kuò)展語法(object spread properties)

this.setState(preState => ({
  owner: {...preState.owner, name: "Jason"};
}))

總結(jié)一下,創(chuàng)建新的狀態(tài)的關(guān)鍵是,避免使用會(huì)直接修改原對象的方法,而是使用可以返回一個(gè)新對象的方法。當(dāng)然,也可以使用一些Immutable的JS庫,如Immutable.js,實(shí)現(xiàn)類似的效果。

那么,為什么React推薦組件的狀態(tài)是不可變對象呢?一方面是因?yàn)椴豢勺儗ο蠓奖愎芾砗驼{(diào)試,了解更多可參考這里;另一方面是出于性能考慮,當(dāng)組件狀態(tài)都是不可變對象時(shí),我們在組件的shouldComponentUpdate方法中,僅需要比較狀態(tài)的引用就可以判斷狀態(tài)是否真的改變,從而避免不必要的render方法的調(diào)用。當(dāng)我們使用React 提供的PureComponent時(shí),更是要保證組件狀態(tài)是不可變對象,否則在組件的shouldComponentUpdate方法中,狀態(tài)比較就可能出現(xiàn)錯(cuò)誤。

下篇預(yù)告:

React 深入系列4:組件的生命周期

新書推薦《React進(jìn)階之路》

作者:徐超

畢業(yè)于浙江大學(xué),碩士,資深前端工程師,長期就職于能源物聯(lián)網(wǎng)公司遠(yuǎn)景智能。8年軟件開發(fā)經(jīng)驗(yàn),熟悉大前端技術(shù),擁有豐富的Web前端和移動(dòng)端開發(fā)經(jīng)驗(yàn),尤其對React技術(shù)棧和移動(dòng)Hybrid開發(fā)技術(shù)有深入的理解和實(shí)踐經(jīng)驗(yàn)。

美團(tuán)點(diǎn)評廣告平臺(tái)大前端團(tuán)隊(duì)招收20192020年前端實(shí)習(xí)生(偏動(dòng)效方向)

有意者郵件:yao.zhou@meituan.com

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94278.html

相關(guān)文章

  • React 深入系列7:React 常用模式

    摘要:本篇是深入系列的最后一篇,將介紹開發(fā)應(yīng)用時(shí),經(jīng)常用到的模式,這些模式并非都有官方名稱,所以有些模式的命名并不一定準(zhǔn)確,請讀者主要關(guān)注模式的內(nèi)容。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使用React。 本篇是React深入系列的最后一篇,將介紹開發(fā)React應(yīng)用時(shí),經(jīng)常用到的模式,這些模式并非都有...

    Chao 評論0 收藏0
  • React 深入系列3:Props State

    摘要:深入系列,深入講解了中的重點(diǎn)概念特性和模式等,旨在幫助大家加深對的理解,以及在項(xiàng)目中更加靈活地使用。下篇預(yù)告深入系列組件的生命周期我的新書進(jìn)階之路已上市,請大家多多支持鏈接京東當(dāng)當(dāng) React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使用React。 React 的核心思想是組件化的思想,而React 組件的定...

    hiyayiji 評論0 收藏0
  • React 深入系列2:組件分類

    摘要:無狀態(tài)組件和有狀態(tài)組件無狀態(tài)組件和有狀態(tài)組件,劃分依據(jù)是根據(jù)組件內(nèi)部是否維護(hù)。展示型組件和容器型組件展示型組件和容器型組件,劃分依據(jù)是根據(jù)組件的職責(zé)。 文:徐超,《React進(jìn)階之路》作者授權(quán)發(fā)布,轉(zhuǎn)載請注明作者及出處 React 深入系列2:組件分類 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使...

    Karrdy 評論0 收藏0
  • React 深入系列2:組件分類

    摘要:無狀態(tài)組件和有狀態(tài)組件無狀態(tài)組件和有狀態(tài)組件,劃分依據(jù)是根據(jù)組件內(nèi)部是否維護(hù)。展示型組件和容器型組件展示型組件和容器型組件,劃分依據(jù)是根據(jù)組件的職責(zé)。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使用React。 React 組件有很多種分類方式,常見的分類方式有函數(shù)組件和類組件,無狀態(tài)組件和有狀態(tài)組件...

    fizz 評論0 收藏0
  • React 深入系列5:事件處理

    摘要:使用匿名函數(shù)先上代碼代碼點(diǎn)擊的事件響應(yīng)函數(shù)是一個(gè)匿名函數(shù),這應(yīng)該是最常見的處理事件響應(yīng)的方式了。事件響應(yīng)函數(shù)的傳參問題事件響應(yīng)函數(shù)默認(rèn)是會(huì)被傳入一個(gè)事件對象作為參數(shù)的。關(guān)于事件響應(yīng)函數(shù),還有一個(gè)地方需要注意。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項(xiàng)目中更加靈活地使用React。 Web應(yīng)用中,事件處理是重要的一...

    willin 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<