Components使得你可以將UI分開(kāi)果覆,變的可以復(fù)用 并且單獨(dú)思考他們的作用和功能炮温。
實(shí)際上玄窝,components就像是javascript的函數(shù)一樣。它接收任意的被稱(chēng)為props的輸入并且返回一個(gè)elements械姻,這個(gè)elements決定了該在屏幕上顯示什么妒蛇。
函數(shù)式Components和類(lèi)式Components
下面這個(gè)簡(jiǎn)單的例子用javascript函數(shù)聲明的方法定義了一個(gè)components:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
這個(gè) 函數(shù)式的component是合法的因?yàn)樗邮樟艘粋€(gè)props對(duì)象為參數(shù)并且返回了一個(gè)element。我們將這樣定義component的方法稱(chēng)之為函數(shù)式的component因?yàn)樗且粋€(gè)Javascript函數(shù)楷拳。
你也可以用ES6語(yǔ)法的class來(lái)定義一個(gè)component:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
上面兩種定義components的方法是等價(jià)的绣夺。
但是類(lèi)式的components會(huì)有額外的一些功能,我們將在下一個(gè)章節(jié)討論它們欢揖。
渲染Component
前面陶耍,我們僅僅遇到了用html標(biāo)簽組成的element:
const element = <div />;
然而,element也可以用我們自定義的component組成:
const element = <Welcome name="Sara" />;
當(dāng)react看到element中有我們自定義的component時(shí)她混,它將會(huì)降JSX的參數(shù)打包成一個(gè)對(duì)象傳遞給component烈钞,我們稱(chēng)這個(gè)被傳遞的對(duì)象為:props。
比如坤按,下面的代碼在頁(yè)面上渲染了一行“Hello毯欣,Sara”的文字:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
讓我們理一理上面這個(gè)例子:
- 我們用ReactDOM.render()這行代碼渲染了<Welcome name="Sara" />這個(gè)element。
2.React將參數(shù)打包為{name: 'Sara'}這個(gè)對(duì)象當(dāng)作props傳遞給Welcome這個(gè)component晋涣。
3.我們自定義的Welcome組件返回了<h1>Hello, Sara</h1>這個(gè)element仪媒。
4.React立即將這個(gè)element渲染到DOM中。
注意谢鹊,一般首字母大寫(xiě)的標(biāo)簽代表我們自定義的component,比如:<div />代表了普通的html標(biāo)簽留凭,而<Welcome>標(biāo)簽代表了一個(gè)自定義組件佃扼。
組合化的Components
components可以將其他components作為他的輸出,這一特性使得我們可以重復(fù)利用以及定義了的componets蔼夜。一個(gè)按鈕兼耀,一個(gè)表單,一個(gè)對(duì)話(huà)框等等求冷,在react中它們都被定義為components瘤运。
比如,我們可以創(chuàng)建渲染多次Welcome組件的應(yīng)用:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
特別的匠题,一個(gè)react應(yīng)用通常會(huì)有一個(gè)單獨(dú)的Component在它的頂端拯坟。然而,如果你需要將react的應(yīng)用合并到一個(gè)已經(jīng)存在的應(yīng)用中韭山,你就需要用button這些最基本的component自底而上的創(chuàng)建一個(gè)component郁季。
注意:Components必須返回一個(gè)單獨(dú)的element冷溃,這也是為什么我們用<div>將返回的element包裹起來(lái)的原因。
提取Components
不要害怕將一個(gè)components分割成幾個(gè)更小的components梦裂。比如似枕,思考這個(gè)Comment組件:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
它接受了author, text, date作為props,在頁(yè)面上渲染了一個(gè)comment頁(yè)面年柠。這個(gè)components會(huì)很難被改變凿歼,而且難以被復(fù)用。讓我們將它里面的一些元素抽象成components冗恨。
首先毅往,我們先抽象出Avatar:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar不知道它被渲染進(jìn)哪里。這就是我們?yōu)槭裁匆獙⑵鋮?shù)定義為user而不是author派近。
現(xiàn)在我們可以將Comment簡(jiǎn)化一下了:
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
接下來(lái)攀唯,我們抽象出UserInfo:
unction UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
現(xiàn)在,Comment被進(jìn)一步簡(jiǎn)化了:
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
抽象出components可能在一開(kāi)始被認(rèn)為是雞肋渴丸,但是在一個(gè)復(fù)雜的app中這種方式是極為重要的侯嘀,因?yàn)樗峁┝丝蓮?fù)用的組件,大大簡(jiǎn)化了整個(gè)app的復(fù)雜度谱轨。
Props是只讀的
無(wú)論你是用函數(shù)式還是類(lèi)式定義Component戒幔,Component都不能自己修改它的props,思考下面的函數(shù):
function sum(a, b) {
return a + b;
}
如同上面這樣的函數(shù)被稱(chēng)為純函數(shù)土童,因?yàn)樗粫?huì)試圖去修改它的輸入值诗茎,并且總是返回確定的基于輸入的值。
相反的献汗,下面這個(gè)函數(shù)就不是純函數(shù)敢订,因?yàn)樗淖兞怂妮斎胫担?/p>
function withdraw(account, amount) {
account.total -= amount;
}
React給予你極大的編碼靈活性,但是有一個(gè)嚴(yán)格的規(guī)則:所有的components必須是純函數(shù)定義
當(dāng)然罢吃,所有的視圖是需要?jiǎng)討B(tài)改變的楚午,在下面的章節(jié)中,我們將會(huì)介紹state的概念尿招。stats允許components改變它的輸入異反饋用戶(hù)的操作矾柜,網(wǎng)絡(luò)響應(yīng)等等。