Quick Start
概覽:
- 如何創建以及嵌套組件
- 如何添加markup 和樣式
- 如何展示數據
- 如何條件渲染,如何渲染列表
- 如何響應事件並更新渲染
- 如何在組件之間共享數據
創建以及嵌套組件
function MyButton() {
return (
<button>I'm a button</button>
);
}
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
注意: <MyButton />
以大寫字母開始, React 組件始終必須以大寫字母開始, 而 HTML tags 必須是小寫的。
export default
關鍵字聲明瞭在這個文件中的 主組件,
用 JSX 書寫 標記(markup)
上面你所見到的 標記語法 被稱作 JSX, JSX 相比較HTML而言,會更加的嚴格, 比必須關閉標籤,例如 <br/>
, 你的組件也不能夠 return
多個 JSX tags, 你必須將返回的標籤包裹, 例如 <div>...</div>
或者 <>...</>
:
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}
添加樣式
在 React 中, 你需要通過 className
屬性來執行一個標籤的 class
:
<img className="avatar" />
接着, 你在一個獨立的 CSS 文件中去書寫CSS 樣式:
/* In your CSS */
.avatar{
border-radius:50%
}
React 並沒有規定你如何去添加這個CSS 文件,在最簡單的情況下,你可以直接添加一個 <link>
tag 到你的 HTML 文件中,然後引入它。 如果你使用框架或者工具來構建 React項目, 那麼你需要參看他們的對應文檔以學習如何添加CSS 文件。
展示數據
JSX 允許你在一個花括號中插入一個變量以展示這個變量值。 例如:
return (
<h1>
{user.name}
</h1>
);
同樣的, 也可以爲一個標籤的屬性指定變量值:
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
實際上, JSX 支持在花括號中解析更加複雜的表達式, 例如:
//App.js
const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
在上面的示例中, style={{}}
並不是一個特殊的語法, 而是style={}
語法花括號中的一個常規的 {}
對象。
條件渲染
在 React 中, 沒有特定的語法去寫 條件 渲染, 替而代之, 你可以直接使用 if
條件語句去完成:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
如果你更加喜歡簡潔的代碼, 那麼你可以使用三元表達式:
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
甚至,如果你壓根都不需要 else
分支,比可以使用一個簡寫的邏輯語法: &&
:
<div>
{isLoggedIn && <AdminPanel />}
</div>
列表渲染
我們通常依賴 的特性,像for
循環, map
去渲染一個列表元素。 例如:
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
在你的組件中, 使用map()
函數去將一個數組轉換爲一個li
元素列表:
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
注意: <li>
有一個 key
屬性 , 對於列表中的每一項, 你都應該傳入一個字符串或者數字,用以標識該 項的唯一性 。這樣,當隨後發生了插入,刪除,或者重排序,React 通過這個key 就能明白髮生了什麼。
const products = [
{ title: 'Cabbage', isFruit: false, id: 1 },
{ title: 'Garlic', isFruit: false, id: 2 },
{ title: 'Apple', isFruit: true, id: 3 },
];
export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
}
事件響應
你可以通過在你的組件中定義一個 event handler 以響應發生對應的事件。
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
注意: onClick={handleClick}
的末尾沒有圓括號, 你只需要將這個事件的定義傳入, React 將會在你隨後點擊這個按鈕的時候再去調用這個事件。
更新屏幕
通常, 你會希望你的組件能夠 “記住” 一些信息, 並展示它。 例如,或許你想要計數按鈕被點擊的次數。 要做到這點, 你需要添加 start
到你的組件。
首先,從 react
引入useState
:
import { useState } from "react";
現在你可以在你的組件內部聲明一個 “狀態” 變量:
function MyButton(){
const [count,setCount] = useState(0);
//...
}
你將會從 useState
中得到兩個東西, 當前的狀態(count
), 以及一個提供給你去更新它的 (setCount
)。 你可以任意定義他們的名字,但是約定俗稱的,我們喜歡寫作 [something, setSomething]
.
按鈕第一次展示的時候, count
將會是 0
,因爲你給 useState()
傳入了0
, 這是它的初始值, 當你想要改變它的時候, 你需要調用 setCount()
方法, 並傳入一個新的值。 :
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
如果你多次渲染了相同的組件,每個組件都會維護一份自己獨有的狀態。
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
記住, 每一個按鈕都會 "記住" 它自己的狀態,並且不會影響其它的按鈕。
使用 Hooks
使用 use
開頭的函數,被稱作 Hooks, useState
是一個 React 內置的 Hook, 你可在這裏找到更多的 Hooks( API reference. ), 你也可以通過組合已有的hook從而創建你自己的 Hooks .
Hooks 相比較其他的函數而言, Hooks 更加具有限制性。 你只能在你的組件的頂部去調用 Hooks , 如果你想要在一個條件或者循環中使用 useState
, 那麼你應該抽離一個新的組件,並把Hooks 放在組件中。
在組件之間共享數據
在之前的示例中, 每個 MyButton
都有着自己獨立的 count
, 但是有的時候,你會希望多個組件共享同一份數據,一處發生變化,其他地方也隨之變化。
還是以這個按鈕的例子來說,如果你希望兩個MyButton
組件共用同一個 count
, 那麼,你需要將 state
從獨立的按鈕組件中 提升 到同時包含這兩個按鈕組件的最近父級組件。
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
注意,在<MyButton count="..." onClick="...">
上定義的這些屬性,將會被包裹爲一個對象作爲參數傳入給function MyButton({ count, onClick }){}
, 這個對象被稱作 props
當你點擊任意一個按鈕的時候, 被傳入的onClick
event handler 都將被觸發, 也就是這個定義在 MyApp
中的handleClick
函數會被觸發, 然後將count
加一。 接着,這個count 又會被傳入到每個 按鈕, 頁面也會隨之發生更新。