目錄
- 1.組件(Components)
- 1.1 什么是組件
- 1.2 定義組件
- 1.3 渲染組件
- 1.4 組合組件
- 1.5 封裝組件
- 2.屬性(Props)
1. 組件(Components)
1.1 什么是組件
組件能讓你將 UI 拆分成各個獨立的、可復用的子單元。組件就像 JavaScript 函數(shù)一樣,接受參數(shù)(也就是 props),返回屏幕上要渲染的 React 元素。各個組件內(nèi)部維護自己的狀態(tài)和 UI,當狀態(tài)發(fā)生改變時,React 會自動重新渲染整個組件,多個組件一起協(xié)作共同構成了 React 應用。
1.2 定義組件
① 以函數(shù)的形式來定義組件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
② 以類(ES6 class)的形式來定義組件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1.3 渲染組件
組件可以當作 React 元素來用。而且我們可以通過 Props 來向組件中傳遞參數(shù):
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);
1.4 組合組件
組件可以互相引用,一個組件中可以在標簽中使用其他組件。
例如, 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')
);
1.5 封裝組件
通過將可重用的代碼封裝成一個獨立的組件,可以提高代碼的復用性和可讀性。
什么時候需要封裝組件?
① 大量的重復 UI 代碼;
② 一個組件內(nèi)部有太多的內(nèi)容,相當復雜時,就需要抽取一部分代碼出來。
舉個例子,我們現(xiàn)在有一個 Comment
組件,通過 props
接收了三個參數(shù) author
(object
), text
(string
), 和 date
(date
) ,用來顯示一條評論:
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>
);
}
很顯然,這里的代碼嵌套太多,難以閱讀,而且里面的一些代碼不能被重用。所以,我們可以嘗試抽取一些代碼進行組件封裝。
第一步,我們先封裝一個 Avatar
組件:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Comment
組件中的代碼就變成了
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>
);
}
即便這樣,Comment
中的代碼感覺還是有點多,我們還可以再進一步抽取封裝一個 UserInfo
組件:
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
這樣 Comment
組件中的代碼就變得非常簡單了:
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>
);
}
2. 屬性(Props)
什么是屬性?大多數(shù)組件在創(chuàng)建時就可以使用各種參數(shù)來進行定制,用于定制的這些參數(shù)就稱為屬性(props)。
屬性是用來給外部向組件內(nèi)部傳值的,組件的內(nèi)部通過讀取 props 來決定如何展示以及處理一些邏輯。
屬性是只讀的,不要試圖在組件內(nèi)部修改外部傳遞進來的 props。
React 組件就像 pure function 一樣(不可以修改傳入的參數(shù)):
// This is a pure function
function sum(a, b) {
return a + b;
}
而不像 impure function(可以修改傳入的參數(shù)):
// This function is impure because it changes its own input.
function withdraw(account, amount) {
account.total -= amount;
}
關于 props
使用的完整示例代碼:
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);
規(guī)則:
- 組件名必須以大寫字母開頭。
- 所有的 React 組件都必須想 pure function 一樣對待它的 props——不要在組件內(nèi)部修改 props。
- 組件必須返回一個單獨的根元素。就像在上文中 4.1 部分的示例代碼一樣,
App
組件返回時,通過一個<div>
標簽將 3 個< Welcome />
標簽包起來了。
延伸閱讀:
- React Official Docs:Components and Props
- React Native 官方文檔:屬性(Props)
- 《React Native 入門與實戰(zhàn)》