什麼是元件:用來實現區域性功能的可複用程式碼片段
比如很多介面會用到“分頁”功能,因此可以將它封裝成獨立的元件
這樣用到分頁的介面只需引入該元件而不必重新寫程式碼
1 定義元件
在 React 中有兩種元件,一種是函式元件,一種是類元件
1.1 函式元件
定義元件最簡單的方式就是編寫 JavaScript 函式
對 React 來說,能夠返回一個 React 元素的 函式 就叫元件
function MyComponent() {
return <h2>我是一個函式元件</h2>;
}
1.2 class 元件
類元件的宣告過程會比較繁瑣一些,需要使用 class、extends 關鍵字,來繼承React.Component{}
render()
函式會返回該類的例項要建立的元素。
class MyComponent extends React.Component {
render() {
return <h2>我是一個class元件</h2>;
}
}
無論是函式元件還是class元件,在 React 中是等效的,不過 class 元件有更多的特性
2 渲染元件
同一個元件在不同介面使用,可能會想要展示不同的內容
比如我們自定義的元件包含了一個h2
標籤,如果我們想要在兩個不同的介面分別展示函式
和class
怎麼辦?
可以在使用元件時新增屬性,react 會將新增的屬性轉換為一個物件傳遞給元件,這個物件稱為"props"
函式元件和class元件可以分別通過“形參”和例項屬性來使用這個物件
比如:
function MyComponent(props) {
console.log(props)
return <h2>我是一個函式元件</h2>;
}
ReactDOM.render(
<MyComponent a="1" b="2" />,
document.getElementById("root")
);
class MyComponent extends React.Component {
render() {
console.log(this.props);
return <h2>我是一個class元件</h2>;
}
}
ReactDOM.render(
<MyComponent a="1" b="2" />,
document.getElementById("root")
);
兩者輸出同樣的物件:
於是我們可以傳入不同的屬性,來讓元件呈現不同的內容:
function MyComponent(props) {
return <h2>我是一個{props.name}元件</h2>;
}
ReactDOM.render(
<MyComponent name="自定義函式" />,
document.getElementById("root")
);
這個例子中發生了這些事:
- 我們呼叫
ReactDOM.render()
函式,並傳入<MyComponent name="自定義函式" />
作為引數。 - React 呼叫
MyComponent
元件,並將{name: '自定義函式'}
作為 props 傳入。 MyComponent
元件將<h2>我是一個自定義函式元件</h2>
元素作為返回值。- React DOM 將 DOM 高效地更新為
<h2>我是一個自定義函式元件</h2>
。
3 注意點
-
元件名稱必須以大寫字母開頭。
-
傳入屬性值為字串和數字的區別:
數字:
<MyComponent a={1} />
字串:
<MyComponent a="1" />
-
多個屬性可以使用擴充套件運算子
const obj = { name: 'React', age: 18 } <MyComponent {...obj} />
注意
{}
不能省略
3 組合元件
元件可以在其輸出中引用其他元件
例如,我們可以建立一個可以多次渲染 Welcome
元件的 App
元件:
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')
);
這就可以讓我們用同一元件來構建不同層次的新元件
4 提取元件
對於一個複雜的元件,我們應該儘量將其拆分為更小的元件,以提高其可維護性和可讀性
例如,參考如下 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。
該元件由於巢狀的關係,變得難以維護,且很難複用它的各個部分。因此,讓我們從中提取一些元件出來。
首先,我們將提取 Avatar
元件:
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
Avatar
不需知道它在 Comment
元件內部是如何渲染的。因此,我們給它的 props 起了一個更通用的名字:user
,而不是 author
。
建議從元件自身的角度命名 props,而不是依賴於呼叫元件的上下文命名。
現在可以在Comment
中引用Avatar
元件了:
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>
);
}
接下來,我們將提取 UserInfo
元件,該元件在使用者名稱旁渲染 Avatar
元件:
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>
);
}
5 Props 的只讀性
對於 props,React 有一個嚴格的規則:
元件無論是使用函式宣告還是通過 class 宣告,都決不能修改自身的 props。
6 計時器
function tick() {
const element = (
<h2>當前時間: {new Date().toLocaleTimeString()}.</h2>
);
ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);
這個例子中,每秒呼叫一次 tick 函式,頁面會更新當前時間
將它封裝為一個元件:
class Clock extends React.Component {
render() {
return <h2>現在時間:{new Date().toLocaleTimeString()}</h2>;
}
}
function tick() {
ReactDOM.render(<Clock />, document.getElementById("root"));
}
setInterval(tick, 1000);
我們將時間寫死在了 JSX 中
如果我們想自己傳入顯示的內容:
class Clock extends React.Component {
render() {
const time = this.props.time;
return <h2>現在時間:{time}</h2>;
}
}
function tick() {
ReactDOM.render(
<Clock time={new Date().toLocaleTimeString()} />,
document.getElementById("root")
);
}
setInterval(tick, 1000);
這樣我們就可以控制顯示的格式
公眾號【前端嘛】