React總結篇之二_設計高質量的React組件

一、易於維護組件的設計要素
1.組件劃分的原則:高內聚低耦合
(1)高內聚:將邏輯緊密相關的內容放在一個組件內。React可以將展示內容的JSX、定義行爲的JavaScript代碼、甚至定義樣式的css,都可以放在一個JavaScript文件中,因此React天生具有高內聚的特點。
(2)低耦合:不同組件之間的依賴關係要儘量弱化,也就是每個組件要儘量獨立。


二、React組件的數據
1.數據分類:
React組件的數據分爲兩種:prop和state。無論prop或者state改變,都可能引發React的重新渲染。那在設計一個組件時,什麼時候選擇prop什麼時候選擇state呢?原則很簡單:prop是組件的對外接口,state是組件的內部狀態,對外用prop,內部用state。

2.Prop:property的縮寫,是從外部傳遞給組件的數據,一個React組件通過定義自己能夠接受的prop就定義了自己的對外公共接口。我們先從外部世界看prop是如何使用的:
<SampleButton id="sample" borderWidth={2} onClick={onButtonClick} style={{color:"red"}}/> 上面創建了名爲SampleButton的組件實例,使用了名字分別爲id、borderWidth、onClick和style的prop。此處注意:HTML組件屬性的值都是字符串類型,即使是內嵌JavaScript,也依然是字符串形式表示代碼。但React組件的prop所能支持的類型除了字符串、可以是任何一種JavaScript語句支持的數據類型,如:數字類型、函數類型、style的值是一個包含color字段的對象,當prop的類型不是字符串類型時,在JSX中必須用花括號{}將prop值包住,所以style的值有兩層花括號,外層花括號代表的是JSX的語法,內層花括號表示這是一個對象常量。
Prop要反饋數據給外部世界,使用函數類型的prop,這等於父組件給了子組件一個回調函數,子組件在恰當的時機調用函數類型的prop,可以帶上必要額參數,這樣就把數據傳遞給外部世界。

3.React要求render函數只能返回一個元素!

4.組件內部接收傳入的prop:
(1)首先是構造函數,如下:
class Counter extends Component {
constructor(props){
super(props);
this.onClickIncrementButon = this.onClickIncrementButon.bind(this);
this.onClickDecrementButon = this.onClickDecrementButon.bind(this);
this.state = {
count : props.initValue || 0
}
}
}
注意:組件定義自己的構造函數,一定要在構造函數的第一行通過super調用父類也就是React.Component的構造函數;如果未調用,那麼組件實例被構造之後,類實例的所有成員函數就無法通過this.props訪問到父組件傳過來的props值。很明顯,給this.props賦值是React.Component構造函數的工作之一。在Counter的構造函數中還給兩個成員函數綁定了當前this的執行環境,因爲ES6方法創建的React類並不自動給我們綁定this到當前實例對象。
(2)讀取prop值:
在構造函數中可以通過props獲得傳入的prop值,在其他函數中可通過this.props訪問傳入prop的值。
const {caption} = this.props;
以上,我們使用了ES6的解構賦值語法,從this.props中獲得了名爲caption的prop值。

5.propTypes檢查:
組件支持哪些prop;
每個prop應該是什麼樣的格式;
如:對於Counter組件的propTypes定義代碼如下:
Counter.propTypes = {
caption : propTypes.string.isRquired,
initVlue : propTypes.number
}
其中要求caption必須是string類型,initVlue必須是number類型,另外,caption帶上了isRquired,表示使用Counter組件必須指定caption,而initVlue如果沒有也沒關係。
propTypes雖然能在開發階段發現代碼中的問題,但是放在產品環境就不大合適了:首先,佔用一些代碼空間,耗CPU計算資源;其次,在產品環境下做propTypes檢查沒有什麼幫助,在最終用戶的瀏覽器Console中輸出這些錯誤信息沒什麼意義。所以,最好的方式是,開發者在代碼中定義propTypes,但在發佈產品代碼時,用一種自動的方式將propTypes去掉。現有的babel-react-optimize具有這個功能,可以通過npm安裝,但是應該確保只在發佈產品代碼時使用它。

6.初始化state:
通常在組件類的構造函數結尾處初始化state,如下:
constructor(props){
......
this.state = {
count:props.initValue || 0
}
}
因爲initValue是一個可選的props,考慮到父組件沒有指定這個props值的情況,我們優先使用傳入屬性的initVlue,如果沒有,就使用默認值0。
組件的state必須是一個JavaScript對象!!!
以上,可使用React的defaultProps功能,如下:
Counter.defaultProps = {0}

7.改變組件的state,如下:
onClickIncrementButton () {
this.setState({count : this.state.count + 1})
}
在代碼中,this.state可以讀取到組件當前的state。注意:改變組件state必須要使用this.setState函數而不能直接去修改this.state。直接修改this.state的值,雖然事實上改變了組件的內部狀態,但只是野蠻的修改了state,並沒有驅動組件進行重新渲染,這樣就無法反應this.state值的變化;而this.setState()函數所做的事情,首先是改變this.state的值,然後驅動組件經歷更新過程,這樣纔有機會讓this.state裏新的值出現在界面上。

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