- 深入淺出React和Redux
- 程墨
- 2131字
- 2019-01-04 20:50:56
2.2.1 React的prop
在React中,prop(property的簡寫)是從外部傳遞給組件的數(shù)據(jù),一個React組件通過定義自己能夠接受的prop就定義了自己的對外公共接口。
每個React組件都是獨立存在的模塊,組件之外的一切都是外部世界,外部世界就是通過prop來和組件對話的。
1.給prop賦值
我們先從外部世界來看,prop是如何使用的,在下面的JSX代碼片段中,就使用了prop:
<SampleButton id="sample" borderWidth={2} onClick={onButtonClick} style={{color: "red"}} />
在上面的例子中,創(chuàng)建了名為SampleButton的組件實例,使用了名字分別為id、border Width、onClick和style的prop,看起來,React組件的prop很像是HTML元素的屬性,不過,HTML組件屬性的值都是字符串類型,即使是內(nèi)嵌JavaScript,也依然是字符串形式表示代碼。React組件的prop所能支持的類型則豐富得多,除了字符串,可以是任何一種JavaScript語言支持的數(shù)據(jù)類型。
比如在上面的SampleButton中,borderWidth就是數(shù)字類型,onClick是函數(shù)類型,style的值是一個包含color字段的對象,當prop的類型不是字符串類型時,在JSX中必須用花括號{}把prop值包住,所以style的值有兩層花括號,外層花括號代表是JSX的語法,內(nèi)層的花括號代表這是一個對象常量。
當外部世界要傳遞一些數(shù)據(jù)給React組件,一個最直接的方式就是通過prop;同樣,React組件要反饋數(shù)據(jù)給外部世界,也可以用prop,因為prop的類型不限于純數(shù)據(jù),也可以是函數(shù),函數(shù)類型的prop等于讓父組件交給了子組件一個回調(diào)函數(shù),子組件在恰當?shù)膶嶋H調(diào)用函數(shù)類型的prop,可以帶上必要的參數(shù),這樣就可以反過來把信息傳遞給外部世界。
對于Counter組件,父組件ControlPanel就是外部世界,我們看ControlPanel是如何用prop傳遞信息給Counter的,代碼如下:
class ControlPanel extends Component { render() { return ( <div> <Counter caption="First" initValue={0} /> <Counter caption="Second" initValue={10} /> <Counter caption="Third" initValue={20} /> </div> ); } }
ControlPanel組件包含三個Counter組件實例,在ControlPanel的render函數(shù)中將這三個子組件實例用div包起來,因為React要求render函數(shù)只能返回一個元素。
提示
雖然React聲稱將來可以支持render返回數(shù)組以支持多個組件,但是到本書寫作時最新版v15.4為止,這個功能依然沒有實現(xiàn)。
在每個Counter組件實例中,都使用了caption和initValue兩個prop。通過名為caption的prop, ControlPanel傳遞給Counter組件實例說明文字。通過名為initValue的prop傳遞給Counter組件一個初始的計數(shù)值。
2.讀取prop值
我們再來看Counter組件內(nèi)部是如何接收傳入的prop的,首先是構(gòu)造函數(shù),代碼如下:
class Counter extends Component { constructor(props) { super(props); this.onClickIncrementButton = this.onClickIncrementButton.bind(this); this.onClickDecrementButton = this.onClickDecrementButton.bind(this); this.state = { count: props.initValue || 0 } }
如果一個組件需要定義自己的構(gòu)造函數(shù),一定要記得在構(gòu)造函數(shù)的第一行通過super調(diào)用父類也就是React.Component的構(gòu)造函數(shù)。如果在構(gòu)造函數(shù)中沒有調(diào)用super(props),那么組件實例被構(gòu)造之后,類實例的所有成員函數(shù)就無法通過this.props訪問到父組件傳遞過來的props值。很明顯,給this.props賦值是React.Component構(gòu)造函數(shù)的工作之一。
在Counter的構(gòu)造函數(shù)中還給兩個成員函數(shù)綁定了當前this的執(zhí)行環(huán)境,因為ES6方法創(chuàng)造的React組件類并不自動給我們綁定this到當前實例對象。
在構(gòu)造函數(shù)的最后,我們可以看到讀取傳入prop的方法,在構(gòu)造函數(shù)中可以通過參數(shù)props獲得傳入prop值,在其他函數(shù)中則可以通過this.props訪問傳入prop的值,比如在Counter組件的render函數(shù)中,我們就是通過this.props獲得傳入的caption, render函數(shù)代碼如下:
render() { const {caption} = this.props; return ( <div> <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button> <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button> <span>{caption} count: {this.state.count}</span> </div> ); }
在上面的代碼中,我們使用了ES6的解構(gòu)賦值(destructuring assignment)語法從this. props中獲得了名為caption的prop值。
3. propTypes檢查
既然prop是組件的對外接口,那么就應(yīng)該有某種方式讓組件聲明自己的接口規(guī)范。簡單說,一個組件應(yīng)該可以規(guī)范以下這些方面:
□ 這個組件支持哪些prop;
□ 每個prop應(yīng)該是什么樣的格式。
React通過propTypes來支持這些功能。
在ES6方法定義的組件類中,可以通過增加類的propTypes屬性來定義prop規(guī)格,這不只是聲明,而且是一種限制,在運行時和靜態(tài)代碼檢查時,都可以根據(jù)propTypes判斷外部世界是否正確地使用了組件的屬性。
比如,對于Counter組件的propTypes定義代碼如下:
Counter.propTypes = { caption: PropTypes.string.isRequired, initValue: PropTypes.number };
其中要求caption必須是string類型,initValue必須是number類型??梢钥吹剑瑑烧叱祟愋筒煌猓€有一個區(qū)別:caption帶上了isRequried,這表示使用Counter組件必須要指定caption;而initValue因為沒有isRequired,則表示如果沒有也沒關(guān)系。
為了驗證propTypes的作用,可以嘗試故意違反propTypes的規(guī)定使用Counter實例,比如在ControlPanel的render函數(shù)中增加下列的代碼:
<Counter caption={123} initValue={20} />
我們在Chrome瀏覽器開發(fā)工具的Console界面,可以看到一個紅色的警告提示,如圖2-2所示。

圖2-2 錯誤prop類型的錯誤提示
這段出錯的含義是,caption屬性預(yù)期是字符串類型,得到的卻是一個數(shù)字類型。
我們嘗試刪掉這個Counter實例的caption屬性,代碼如下:
<Counter initValue={20} />
這時可以看到Console選項卡中依然有紅色警告信息,如圖2-3所示。

圖2-3 缺失必須存在prop的錯誤提示
提示的含義是,caption是Counter必需的屬性,但是卻沒有賦值。
很明顯,有了propTypes的檢查,可以很容易發(fā)現(xiàn)對prop的不正確使用方法,可盡早發(fā)現(xiàn)代碼中的錯誤。
從上面可以看得出來propTypes檢查可以防止不正確的prop使用方法,那么如果組件根本就沒有定義propTypes會怎么樣呢?
可以嘗試在src/Counter.js文件中刪除掉那一段給Counter.propTypes賦值的語句,在瀏覽器Console里可以看到紅色警告不再出現(xiàn)??梢?,沒有propTypes定義,組件依然能夠正常工作,而且,即使在上面propTypes檢查出錯的情況下,組件依舊能工作。也就是說propTypes檢查只是一個輔助開發(fā)的功能,并不會改變組件的行為。
propTypes雖然能夠在開發(fā)階段發(fā)現(xiàn)代碼中的問題,但是放在產(chǎn)品環(huán)境中就不大合適了。
首先,定義類的propTypes屬性,無疑是要占用一些代碼空間,而且propTypes檢查也是要消耗CPU計算資源的。其次,在產(chǎn)品環(huán)境下做propTypes檢查沒有什么幫助,畢竟,propTypes產(chǎn)生的這些錯誤信息只有開發(fā)者才能看得懂,放在產(chǎn)品環(huán)境下,在最終用戶的瀏覽器Console中輸出這些錯誤信息沒什么意義。
所以,最好的方式是,開發(fā)者在代碼中定義propTypes,在開發(fā)過程中避免犯錯,但是在發(fā)布產(chǎn)品代碼時,用一種自動的方式將propTypes去掉,這樣最終部署到產(chǎn)品環(huán)境的代碼就會更優(yōu)?,F(xiàn)有的babel-react-optimize就具有這個功能,可以通過npm安裝,但是應(yīng)該確保只在發(fā)布產(chǎn)品代碼時使用它。
- 基于粒計算模型的圖像處理
- C# 2012程序設(shè)計實踐教程 (清華電腦學(xué)堂)
- Instant 960 Grid System
- R語言數(shù)據(jù)可視化實戰(zhàn)
- Learning Linux Binary Analysis
- 人人都是網(wǎng)站分析師:從分析師的視角理解網(wǎng)站和解讀數(shù)據(jù)
- Mastering Linux Network Administration
- Learning Three.js:The JavaScript 3D Library for WebGL
- R語言與網(wǎng)絡(luò)輿情處理
- IBM Cognos Business Intelligence 10.1 Dashboarding cookbook
- Babylon.js Essentials
- Unity&VR游戲美術(shù)設(shè)計實戰(zhàn)
- Spring MVC+MyBatis開發(fā)從入門到項目實踐(超值版)
- Developing SSRS Reports for Dynamics AX
- 代替VBA!用Python輕松實現(xiàn)Excel編程