組件 & Props
組件從概念上看就像是函數,它可以接收任意的輸入值(稱之爲“props”),並返回一個需要在頁面上展示的React元素
函數定義/類定義組件
定義一個組件最簡單的方式是使用JavaScript函數:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
該函數是一個有效的React組件,它接收一個單一的“props”對象並返回了一個React元素。我們之所以稱這種類型的組件爲函數定義組件,是因爲從字面上來看,它就是一個JavaScript函數。
你也可以使用 ES6 class 來定義一個組件:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
上面兩個組件在React中是相同的。
組件渲染
在前面,我們遇到的React元素都只是DOM標籤:
const element = <div />;
然而,React元素也可以是用戶自定義的組件:
const element = <Welcome name="Sara" />;
當React遇到的元素是用戶自定義的組件,它會將JSX屬性作爲單個對象傳遞給該組件,這個對象稱之爲“props”。
例如,這段代碼會在頁面上渲染出”Hello,Sara”:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
我們來回顧一下在這個例子中發生了什麼:
- 我們對
<Welcome name="Sara" />
元素調用了ReactDOM.render()
方法。 - React將
{name: 'Sara'}
作爲props傳入並調用Welcome
組件。 Welcome
組件將<h1>Hello, Sara</h1>
元素作爲結果返回。- React DOM將DOM更新爲
<h1>Hello, Sara</h1>
。
警告:
組件名稱必須以大寫字母開頭。
例如,<div />
表示一個DOM標籤,但 <Welcome />
表示一個組件,並且在使用該組件時你必須定義或引入它。
組合組件
組件可以在它的輸出中引用其它組件,這就可以讓我們用同一組件來抽象出任意層次的細節。在React應用中,按鈕、表單、對話框、整個屏幕的內容等,這些通常都被表示爲組件。
例如,我們可以創建一個App
組件,用來多次渲染Welcome
組件:
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')
);
通常,一個新的React應用程序的頂部是一個App
組件。但是,如果要將React集成到現有應用程序中,則可以從下而上使用像Button
這樣的小組件作爲開始,並逐漸運用到視圖層的頂部。
警告:
組件的返回值只能有一個根元素。這也是我們要用一個<div>
來包裹所有<Welcome />
元素的原因。
組合組件
組件可以在它的輸出中引用其它組件,這就可以讓我們用同一組件來抽象出任意層次的細節。在React應用中,按鈕、表單、對話框、整個屏幕的內容等,這些通常都被表示爲組件。
通常,一個新的React應用程序的頂部是一個App
組件。但是,如果要將React集成到現有應用程序中,則可以從下而上使用像Button
這樣的小組件作爲開始,並逐漸運用到視圖層的頂部。
警告:
組件的返回值只能有一個根元素。這也是我們要用一個
<div>
來包裹所有<Welcome />
元素的原因。
提取組件
你可以將組件切分爲更小的組件,這沒什麼好擔心的。
這個組件接收author
(對象)、text
(字符串)、以及date
(Date對象)作爲props,用來描述一個社交媒體網站上的評論。
這個組件由於嵌套,變得難以被修改,可複用的部分也難以被複用。所以讓我們從這個組件中提取出一些小組件。
提取組件一開始看起來像是一項單調乏味的工作,但是在大型應用中,構建可複用的組件完全是值得的。當你的UI中有一部分重複使用了好幾次(比如,Button
、Panel
、Avatar
),或者其自身就足夠複雜(比如,App
、FeedStory
、Comment
),類似這些都是抽象成一個可複用組件的絕佳選擇,這也是一個比較好的做法。function formatDate(date) {
return date.toLocaleDateString();
}
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name} />
);
}
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
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>
);
}
const comment = {
date: new Date(),
text: 'I hope you enjoy learning React!',
author: {
name: 'Hello Kitty',
avatarUrl: 'http://placekitten.com/g/64/64'
}
};
ReactDOM.render(
<Comment
date={comment.date}
text={comment.text}
author={comment.author} />,
document.getElementById('root')
);