本文僅作為個(gè)人學(xué)習(xí)React的筆記默责,文中省略了基礎(chǔ)的知識(shí)點(diǎn)和術(shù)語(yǔ)何暇。在閱讀本文前但壮,默認(rèn)已經(jīng)準(zhǔn)備好了React的運(yùn)行環(huán)境冀泻。
本文重點(diǎn)記錄React的組件部分,且不使用ES6的特性蜡饵。
如何創(chuàng)建一個(gè)組件弹渔?
創(chuàng)建一個(gè)組件使用React.createClass(object)
方法,作為組件溯祸,該方法返回的變量名稱必須以大寫字母開頭肢专。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message!</h1>;
}
});
在React.createClass參數(shù)必須是一個(gè)JS對(duì)象,其必須實(shí)現(xiàn)一個(gè)名為render方法焦辅,該方法的返回值是一個(gè)只包含一個(gè)根節(jié)點(diǎn)的Dom對(duì)象(可以包含自定義組件)博杖。
組件的屬性 props
組件的屬性可以使用this.props
來(lái)獲取,該屬性值來(lái)源于組件調(diào)用時(shí)的定義筷登,屬性在定義后就不能被修改剃根,除非重新生成組件。
屬性定義示例:
ReactDOM.render(
<HelloMessage name="zsea.Message" />,
document.getElementById('example')
);
其中前方,組件包含名稱為name屬性狈醉,可以能過(guò)this.props.name
來(lái)獲取。
特殊屬性:props.children
該屬性為組件的子對(duì)象惠险,若子對(duì)象只有一個(gè)舔糖,該值為一個(gè)JS對(duì)象,若有多個(gè)莺匠,則為JS數(shù)組金吗。當(dāng)為JS數(shù)組時(shí),呈現(xiàn)的子對(duì)象必須包含key
屬性。
為了簡(jiǎn)化操作摇庙,React提供了方法React.Children.map(children,function(){})
用于遍歷子對(duì)象旱物,使用該方法遍歷時(shí),不需要區(qū)分是JS數(shù)組還是JS對(duì)象卫袒。
示例:
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
);
屬性驗(yàn)證 PropTypes
為保證組件被正確使用宵呛,React引入了
propTypes
,用于對(duì)屬性進(jìn)行校驗(yàn)夕凝,同時(shí)宝穗,React.PropTypes
提供了大量的驗(yàn)證器來(lái)驗(yàn)證傳入數(shù)據(jù)的有效性。當(dāng)向 props 傳入無(wú)效數(shù)據(jù)時(shí)码秉,JavaScript 控制臺(tái)會(huì)拋出警告逮矛。為了性能考慮,建議只在開發(fā)環(huán)境驗(yàn)證 propTypes转砖。
下面用例子來(lái)說(shuō)明不同驗(yàn)證器的區(qū)別:
React.createClass({
propTypes: {
// 可以聲明 prop 為指定的 JS 基本類型须鼎。默認(rèn)
// 情況下,這些 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,
// 所有可以被渲染的對(duì)象:數(shù)字晋控,
// 字符串,DOM 元素或包含這些類型的數(shù)組(or fragment) 姓赤。
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 你同樣可以斷言一個(gè) prop 是一個(gè)類的實(shí)例赡译。
// 用 JS 的 instanceof 操作符聲明 prop 為類的實(shí)例。
optionalMessage: React.PropTypes.instanceOf(Message),
// 你可以用 enum 的方式
// 確保你的 prop 被限定為指定值不铆。
optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
// 指定的多個(gè)對(duì)象類型中的一個(gè)
optionalUnion: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
]),
// 指定類型組成的數(shù)組
optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
// 指定類型的屬性構(gòu)成的對(duì)象
optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
// 特定形狀參數(shù)的對(duì)象
optionalObjectWithShape: React.PropTypes.shape({
color: React.PropTypes.string,
fontSize: React.PropTypes.number
}),
// 你可以在任意東西后面加上 `isRequired`
// 來(lái)確保 如果 prop 沒(méi)有提供 就會(huì)顯示一個(gè)警告蝌焚。
requiredFunc: React.PropTypes.func.isRequired,
// 不可空的任意類型
requiredAny: React.PropTypes.any.isRequired,
// 你可以自定義一個(gè)驗(yàn)證器。如果驗(yàn)證失敗需要返回一個(gè) Error 對(duì)象狂男。
// 不要直接使用 `console.warn` 或拋異常综看,
// 因?yàn)檫@在 `oneOfType` 里不起作用品腹。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Validation failed!');
}
}
},
/* ... */
});
React也提供了針對(duì)子對(duì)象的驗(yàn)證器
用
React.PropTypes.element
你可以指定僅有一個(gè)子級(jí)能被傳送給組件岖食。
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
return (
<div>
{this.props.children} // 這里必須是一個(gè)元素否則就會(huì)警告
</div>
);
}
});
默認(rèn)屬性 getDefaultProps
當(dāng)父級(jí)沒(méi)有傳入 props 時(shí),getDefaultProps()
可以保證 this.props.value
有默認(rèn)值舞吭,注意 getDefaultProps 的結(jié)果會(huì)被緩存泡垃。得益于此,你可以直接使用 props羡鸥,而不必寫手動(dòng)編寫一些重復(fù)或無(wú)意義的代碼蔑穴。
該接口要求返回一個(gè)JS對(duì)象。
示例:
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
});
組件的狀態(tài) state
組件的屬性在被定義后惧浴,是不允放被修改的存和。但是,React同時(shí)也提供了組件的狀態(tài),狀態(tài)是允許被在內(nèi)部修改的捐腿。
獲取組件狀態(tài)使用this.state
纵朋,this.state
是一個(gè)JS對(duì)象。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
其中茄袖,time為組件的一個(gè)狀態(tài)操软。
狀態(tài)的修改 setState
在語(yǔ)言層面,我們可以直接使用'='來(lái)修改組件的狀態(tài)(this.state)宪祥,但是聂薪,這種方法的修改并不能使組件觸發(fā)render,修改后的狀態(tài)并不能反映在WEB界面上蝗羊。
Reace為我們提供了統(tǒng)一的狀態(tài)修改方法:this.setState(state)
藏澳,參數(shù)state是一個(gè)JS對(duì)象,其中只需要標(biāo)識(shí)需要被修改的對(duì)象肘交,而this.state中已經(jīng)存在的非同名對(duì)象不會(huì)被覆蓋笆载。該方法僅能在組件內(nèi)部調(diào)用。
初始狀態(tài) getInitialState
狀態(tài)是由組件內(nèi)部進(jìn)行控制涯呻,在沒(méi)有任何方法調(diào)用前凉驻,React提供了一個(gè)接口用于組件狀態(tài)的初始化:getInitialState
,該接口要求返回一個(gè)JS對(duì)象复罐。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:'2016-12-23'};
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
在getInitialState接口中涝登,可以使用組件的屬性值做為組件的狀態(tài)。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:this.props.time};//time屬性作為組件的time的狀態(tài)值
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
總結(jié)
一個(gè)React組件效诅,提供了兩個(gè)接口胀滚、一個(gè)方法、三個(gè)對(duì)象乱投。
兩個(gè)接口:
- render
- getInitialState
其中render用于組件的呈現(xiàn)咽笼,在調(diào)用方法this.setState(state)
時(shí)會(huì)被自動(dòng)調(diào)用。getInitialState
用于返回組件內(nèi)部的初始狀態(tài)戚炫,可以使用屬性值作為組件狀態(tài)剑刑。
一個(gè)方法:
- setState(state)
該方法用于重新設(shè)置組件的狀態(tài)值,并且根據(jù)需要觸發(fā)render
双肤。
三個(gè)對(duì)象:
- state
- props
- propTypes
其中state
存儲(chǔ)的組件狀態(tài)施掏,可以能過(guò)setState
進(jìn)行修改;
props存儲(chǔ)的組件屬性茅糜,不能被修改七芭;同時(shí),props包含一個(gè)特列對(duì)象:props.children
蔑赘,該對(duì)象中包含的時(shí)子對(duì)象狸驳。
propTypes
為一個(gè)JS對(duì)象预明,該對(duì)象用于校驗(yàn)組件的屬性是否正在確。