本文僅作為個人學習React的筆記,文中省略了基礎的知識點和術語。在閱讀本文前,默認已經準備好了React的運行環境。
本文重點記錄React的組件部分,且不使用ES6的特性。
如何創建一個組件?
創建一個組件使用React.createClass(object)
方法,作為組件,該方法返回的變量名稱必須以大寫字母開頭。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message!</h1>;
}
});
在React.createClass參數必須是一個JS對象,其必須實現一個名為render方法,該方法的返回值是一個只包含一個根節點的Dom對象(可以包含自定義組件)。
組件的屬性 props
組件的屬性可以使用this.props
來獲取,該屬性值來源于組件調用時的定義,屬性在定義后就不能被修改,除非重新生成組件。
屬性定義示例:
ReactDOM.render(
<HelloMessage name="zsea.Message" />,
document.getElementById('example')
);
其中,組件包含名稱為name屬性,可以能過this.props.name
來獲取。
特殊屬性:props.children
該屬性為組件的子對象,若子對象只有一個,該值為一個JS對象,若有多個,則為JS數組。當為JS數組時,呈現的子對象必須包含key
屬性。
為了簡化操作,React提供了方法React.Children.map(children,function(){})
用于遍歷子對象,使用該方法遍歷時,不需要區分是JS數組還是JS對象。
示例:
var NotesList = React.createClass({
render: function() {
return (
<ol>
{
React.Children.map(this.props.children, function (child,_index) {
return <li key={_index}>{child}</li>;
})
}
</ol>
);
}
});
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.body
);
屬性驗證 PropTypes
為保證組件被正確使用,React引入了
propTypes
,用于對屬性進行校驗,同時,React.PropTypes
提供了大量的驗證器來驗證傳入數據的有效性。當向 props 傳入無效數據時,JavaScript 控制臺會拋出警告。為了性能考慮,建議只在開發環境驗證 propTypes。
下面用例子來說明不同驗證器的區別:
React.createClass({
propTypes: {
// 可以聲明 prop 為指定的 JS 基本類型。默認
// 情況下,這些 prop 都是可傳可不傳的。
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
// 所有可以被渲染的對象:數字,
// 字符串,DOM 元素或包含這些類型的數組(or fragment) 。
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 你同樣可以斷言一個 prop 是一個類的實例。
// 用 JS 的 instanceof 操作符聲明 prop 為類的實例。
optionalMessage: React.PropTypes.instanceOf(Message),
// 你可以用 enum 的方式
// 確保你的 prop 被限定為指定值。
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 指定的多個對象類型中的一個
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 指定類型組成的數組
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 指定類型的屬性構成的對象
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 特定形狀參數的對象
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 你可以在任意東西后面加上 `isRequired`
// 來確保 如果 prop 沒有提供 就會顯示一個警告。
requiredFunc: React.PropTypes.func.isRequired,
// 不可空的任意類型
requiredAny: React.PropTypes.any.isRequired,
// 你可以自定義一個驗證器。如果驗證失敗需要返回一個 Error 對象。
// 不要直接使用 `console.warn` 或拋異常,
// 因為這在 `oneOfType` 里不起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
},
/* ... */
});
React也提供了針對子對象的驗證器
用
React.PropTypes.element
你可以指定僅有一個子級能被傳送給組件。
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
return (
<div>
{this.props.children} // 這里必須是一個元素否則就會警告
</div>
);
}
});
默認屬性 getDefaultProps
當父級沒有傳入 props 時,getDefaultProps()
可以保證 this.props.value
有默認值,注意 getDefaultProps 的結果會被緩存。得益于此,你可以直接使用 props,而不必寫手動編寫一些重復或無意義的代碼。
該接口要求返回一個JS對象。
示例:
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
});
組件的狀態 state
組件的屬性在被定義后,是不允放被修改的。但是,React同時也提供了組件的狀態,狀態是允許被在內部修改的。
獲取組件狀態使用this.state
,this.state
是一個JS對象。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
其中,time為組件的一個狀態。
狀態的修改 setState
在語言層面,我們可以直接使用'='來修改組件的狀態(this.state),但是,這種方法的修改并不能使組件觸發render,修改后的狀態并不能反映在WEB界面上。
Reace為我們提供了統一的狀態修改方法:this.setState(state)
,參數state是一個JS對象,其中只需要標識需要被修改的對象,而this.state中已經存在的非同名對象不會被覆蓋。該方法僅能在組件內部調用。
初始狀態 getInitialState
狀態是由組件內部進行控制,在沒有任何方法調用前,React提供了一個接口用于組件狀態的初始化:getInitialState
,該接口要求返回一個JS對象。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:'2016-12-23'};
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
在getInitialState接口中,可以使用組件的屬性值做為組件的狀態。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:this.props.time};//time屬性作為組件的time的狀態值
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
總結
一個React組件,提供了兩個接口、一個方法、三個對象。
兩個接口:
- render
- getInitialState
其中render用于組件的呈現,在調用方法this.setState(state)
時會被自動調用。getInitialState
用于返回組件內部的初始狀態,可以使用屬性值作為組件狀態。
一個方法:
- setState(state)
該方法用于重新設置組件的狀態值,并且根據需要觸發render
。
三個對象:
- state
- props
- propTypes
其中state
存儲的組件狀態,可以能過setState
進行修改;
props存儲的組件屬性,不能被修改;同時,props包含一個特列對象:props.children
,該對象中包含的時子對象。
propTypes
為一個JS對象,該對象用于校驗組件的屬性是否正在確。