å¿«éå ¥é¨
欢è¿è®¿é® React ææ¡£ï¼æ¬é¡µå°åæ¨ä»ç» 80% ç React æ¦å¿µï¼è¿äºæ¦å¿µå°æ¯æ¨æ¥å¸¸å¼åä¸ç»å¸¸ç¨å°çã
You will learn
- å¦ä½å建并åµå¥ç»ä»¶
- How to add markup and styles
- å¦ä½å±ç¤ºæ°æ®
- How to render conditions and lists
- å¦ä½ååºäºä»¶å¹¶æ´æ°å±å¹æ¾ç¤º
- å¦ä½å¨ç»ä»¶é´å ±äº«æ°æ®
å建并åµå¥ç»ä»¶
React åºç¨ç¨åºæ¯ç±ç»ä»¶ï¼componentï¼ç»æçãç»ä»¶æ¯ UIï¼ç¨æ·çé¢ï¼çç»æé¨åï¼æ¥æèªå·±çé»è¾åå¤è§ãä¸ä¸ªç»ä»¶å¯ä»¥å°å°ä¸ä¸ªæé®ï¼å¤§å°æ´ä¸ªé¡µé¢ã
React ç»ä»¶å°±æ¯ JavaScript 彿°ï¼functionï¼ï¼æ¤ç±»å½æ°è¿åç±æ ç¾è¯è¨ç¼åçç¨æ·çé¢ï¼
function MyButton() {
return (
<button>Click me</button>
);
}ç°å¨ï¼ä½ å·²ç»å£°æäº MyButton ç»ä»¶ï¼æ¥ä¸æ¥å°±å¯ä»¥å°å
¶åµå
¥å°å
¶å®ç»ä»¶ä¸äºï¼
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}请注æï¼<MyButton /> æ ç¾ä»¥å¤§å忝å¼å¤´ï¼è¿æ ·å°±è½ä¾¿äºè¯å«è¿ä¸ªæ¯ä¸ä¸ª React ç»ä»¶ãReact ç»ä»¶çåç§°å¿
é¡»å§ç»ä»¥å¤§å忝å¼å¤´ï¼è HTML æ ç¾å¿
é¡»å
¨é¨ä¸ºå°å忝ã
ççææï¼
function MyButton() {
return (
<button>
Click me
</button>
);
}
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
export default å
³é®å卿件䏿 æäºä¸»è¦ç»ä»¶ãå¦æä½ å¯¹æ¤ JavaScript è¯æ³è¿ä¸çæï¼è¯·åè MDN å javascript.info ä¸çåèæåã
ç¼å JSX è¯æ³çæ ç¾
ä½ å¨åé¢çå°çæ è®°è¯è¨ï¼markup syntaxï¼ç§°ä¸º JSXãJSX 䏿¯å¿ é¡»è¦ç¨çï¼ä½æ¯å ä¸ºä½¿ç¨æ¹ä¾¿ï¼æä»¥å¤§å¤æ° React 项ç®é½ä½¿ç¨ JSXãææ æä»¬æ¨èçç¨äºæ¬å°å¼åçå·¥å · é½èªå¸¦å¯¹ JSX çæ¯æã
JSX çè¯æ³æ¯ HTML æ´ä¸¥æ ¼ã类似 <br /> è¿æ ·çæ ç¾æ¯å¿
é¡»è¦å
³éçãå¹¶ä¸ï¼ç»ä»¶ä¹ä¸è½è¿åå¤ä¸ªå¹¶åæé«å±çº§ç JSX æ ç¾ï¼ä½ å¿
é¡»ä¸ºæææé«å±çº§çæ ç¾æ·»å ä¸ä¸ªå
±åçç¶æ ç¾ï¼ä¾å¦ä½¿ç¨ <div>...</div> æ <>...</> ä½ä¸ºç¶æ ç¾ï¼
function AboutPage() {
return (
<>
<h1>About</h1>
<p>Hello there.<br />How do you do?</p>
</>
);
}å¦æä½ éè¦å°å¤§é HTML 代ç ç§»æ¤å° JSX è¯æ³ï¼å¯ä»¥ä½¿ç¨è¿ä¸ª å¨çº¿è½¬æ¢å¨ã
æ·»å æ ·å¼
å¨ React ä¸ï¼éè¿ className è¿ä¸ªå±æ§æ¥æå® CSS ç±»ãå®å HTML ç class 屿§çåè½æ¯ä¸æ ·çï¼
<img className="avatar" />ç¶åå¨ä¸ä¸ªåç¬ç CSS æä»¶ä¸ä¸ºå ¶ç¼å CSS æ ·å¼ï¼
/* In your CSS */
.avatar {
border-radius: 50%;
}React 没æè§å®å¦ä½æ·»å CSS æä»¶ãæç®åçæ¹å¼æ¯æ·»å ä¸ä¸ª <link> æ ç¾å°é¡µé¢ç HTML 代ç ä¸ãå¦æä½ ä½¿ç¨äºæå»ºå·¥å
·ææ¡æ¶ï¼è¯·æ¥é
å
¶ç¸å
³ææ¡£ï¼ä»¥ä¾¿äºè§£å¦ä½å° CSS æä»¶æ·»å å°ä½ ç项ç®ä¸ã
æ¾ç¤ºæ°æ®
JSX å
è®¸ä½ å°æ ç¾è¯è¨æ··å
¥å° JavaScript 代ç ä¸ãéè¿è±æ¬å·å¯ä»¥è®©ä½ 卿 ç¾è¯è¨ä¸è¾åº JavaScript åéï¼å¹¶å°å
¶å±ç¤ºç»ç¨æ·ãä¾å¦ï¼ä»¥ä¸ä»£ç å°æ¾ç¤º user.name çå¼ï¼
return (
<h1>
{user.name}
</h1>
);ä½ ä¹å¯ä»¥å¨ JSX ç屿§ä¸åµå
¥ JavaScript 代ç ï¼ä½æ¯å¿
须使ç¨è±æ¬å·ï¼ä¸è½ä½¿ç¨å¼å·ãä¾å¦ï¼className="avatar" å° "avatar" å符串ä½ä¸º CSS ç±»è¿è¡ä¼ éï¼è src={user.imageUrl} é¦å
读å user.imageUrl åéçå¼ï¼ç¶åå°è¯¥å¼ä½ä¸º src ç屿§è¿è¡ä¼ éï¼
return (
<img
className="avatar"
src={user.imageUrl}
/>
);ä½ ä¹å¯ä»¥å¨ JSX ä¸éè¿è±æ¬å·æ·»å æ´å¤æç JavaScript 表达å¼ï¼ä¾å¦ åç¬¦ä¸²æ¼æ¥ï¼
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={{}} 䏿¯ä¸ç§ç¹æ®è¯æ³ï¼èæ¯ {} æä»£è¡¨ç对象ï¼objectï¼è¢«æ¾å¨äº style={ } çè±æ¬å·éé¢äºãå½ CSS æ ·å¼ä¾èµ JavaScript åéç弿¶ï¼å¯ä»¥éè¿ style 屿§è¿è¡è®¾ç½®ã
Conditional rendering
å¨ React ä¸ï¼æ²¡æç¨äºä¹¦åæ¡ä»¶è¡¨è¾¾å¼çç¹æ®è¯æ³ãç¸åï¼ä½ åªé使ç¨å¸¸è§ç JavaScript æ¡ä»¶è¡¨è¾¾å¼å³å¯ãä¾å¦ï¼ä½ å¯ä»¥ä½¿ç¨ if è¯å¥æ¥æ ¹æ®æ¡ä»¶å
å«ä¸åç JSX 代ç ï¼
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);å¦æä½ åæ¬¢æ´ç´§åç代ç ï¼å¯ä»¥ä½¿ç¨ ? æ¡ä»¶è¿ç®ç¬¦ãä¸ if ä¸åï¼ä»è½ä¸ JSX è¯æ³æ··å书åï¼
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>å½ä½ ä¸éè¦ else 忝æ¶ï¼è¿å¯ä»¥ä½¿ç¨æ´ç®çç && è¯æ³ï¼
<div>
{isLoggedIn && <AdminPanel />}
</div>ææè¿äºæ¹æ³All of these approaches also work for conditionally specifying attributes. If youâre unfamiliar with some of this JavaScript syntax, you can start by always using if...else.
Rendering lists
You will rely on JavaScript features like for loop and the array map() function to render lists of components.
ä¾å¦ï¼åè®¾ä½ æä¸ä¸ªäº§åå表ï¼
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];Inside your component, use the map() function to transform an array of products into an array of <li> items:
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);Notice how <li> has a key attribute. For each item in a list, you should pass a string or a number that uniquely identifies that item among its siblings. Usually, a key should be coming from your data, such as a database ID. React will rely on your keys to understand what happened if you later insert, delete, or reorder the items.
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>
);
}
Responding to events
You can respond to events by declaring event handler functions inside your components:
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}Notice how onClick={handleClick} has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.
Updating the screen
Often, youâll want your component to ârememberâ some information and display it. For example, maybe you want to count the number of times a button is clicked. To do this, add state to your component.
First, import useState from React:
import { useState } from 'react';Now you can declare a state variable inside your component:
function MyButton() {
const [count, setCount] = useState(0);You will get two things from useState: the current state (count), and the function that lets you update it (setCount). You can give them any names, but the convention is to call them like [something, setSomething].
The first time the button is displayed, count will be 0 because you passed 0 to useState(). When you want to change state, call setCount() and pass the new value to it. Clicking this button will increment the counter:
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}React will call your component function again. This time, count will be 1. Then it will be 2. And so on.
If you render the same component multiple times, each will get its own state. Try clicking each button separately:
import { useState } from 'react';
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
<MyButton />
</div>
);
}
Notice how each button âremembersâ its own count state and doesnât affect other buttons.
Using Hooks
Functions starting with use are called Hooks. useState is a built-in Hook provided by React. You can find other built-in Hooks in the React API reference. You can also write your own Hooks by combining the existing ones.
Hooks are more restrictive than regular functions. You can only call Hooks at the top level of your components (or other Hooks). If you want to useState in a condition or a loop, extract a new component and put it there.
Sharing data between components
In the previous example, each button had its own independent counter:
- MyApp
- MyButton (count: 3)
- MyButton (count: 1)
- MyButton (count: 2)However, youâll often need components to share data and always update together.
To make all buttons display the same count and update together, you need to move the state from the individual buttons âupwardsâ to the closest component containing all of them. In this example, it is MyApp:
- MyApp (count: 3)
- MyButton
- MyButton
- MyButtonHereâs how you can express this in code.
First, move the state up from MyButton into MyApp:
function MyButton() {
// ... we're moving code from here ...
}
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
<MyButton />
</div>
);
}Then, pass the state down from MyApp to each MyButton, together with the shared click handler. You can pass information to MyButton using the JSX curly braces, just like you previously did with built-in tags like <img>:
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} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}The information you pass down like this is called props. Now the MyApp component contains the count state and the handleClick event handler, and passes both of them down as props to each of the buttons.
Finally, change MyButton to read the props you have passed from its parent component:
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}When you click the button, the onClick handler fires. Each buttonâs onClick prop was set to the handleClick function inside MyApp, so the code inside of it runs. That code calls setCount(count + 1), incrementing the count state variable. The new count value is passed as a prop to each button, so they all show the new value.
This is called âlifting state upâ. By moving state up, weâve shared it between components.
import { useState } from 'react';
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
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} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
Next Steps
By now, you know the basics of how to write React code!
Head to Thinking in React to see how it feels to build a UI with React in practice.