快速入门
欢迎来到 React 文档!本页面将向你介绍你在日常工作中会用到的 80% 的 React 概念。
你将学到
- 如何创建和嵌套组件
- 如何添加标记和样式
- 如何显示数据
- 如何渲染条件和列表
- 如何响应事件并更新屏幕
- 如何在组件之间共享数据
创建和嵌套组件
React 应用程序由组件构成。组件是 UI(用户界面)的一部分,它有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。
React 组件是返回标记的 JavaScript 函数
function MyButton() {
return (
<button>I'm a button</button>
);
}
现在你已经声明了 MyButton
,你可以将其嵌套到另一个组件中
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
注意,<MyButton />
以大写字母开头。这就是你如何知道它是一个 React 组件。React 组件名称必须始终以大写字母开头,而 HTML 标签必须是小写。
看看结果
function MyButton() { return ( <button> I'm a button </button> ); } export default function MyApp() { return ( <div> <h1>Welcome to my app</h1> <MyButton /> </div> ); }
该 export default
关键字指定了文件中的主组件。如果你不熟悉某些 JavaScript 语法,MDN 和 javascript.info 有很好的参考资料。
用 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 文件。在最简单的情况下,你将向你的 HTML 添加一个 <link>
标签。如果你使用构建工具或框架,请查看其文档以了解如何将 CSS 文件添加到项目中。
显示数据
JSX 让你可以将标记放入 JavaScript 中。花括号让你可以“逃回”到 JavaScript 中,这样你就可以嵌入代码中的一些变量并将其显示给用户。例如,这将显示 user.name
return (
<h1>
{user.name}
</h1>
);
你也可以从 JSX 属性中“逃回 JavaScript”,但你必须使用花括号而不是引号。例如,className="avatar"
将 "avatar"
字符串作为 CSS 类传递,但 src={user.imageUrl}
读取 JavaScript user.imageUrl
变量值,然后将该值作为 src
属性传递
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
你也可以在 JSX 花括号中放置更复杂的表达式,例如 字符串连接
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={ }
JSX 花括号内的普通 {}
对象。当你的样式依赖于 JavaScript 变量时,可以使用 style
属性。
条件渲染
在 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>
所有这些方法也适用于有条件地指定属性。如果你不熟悉其中的一些 JavaScript 语法,你可以从始终使用 if...else
开始。
渲染列表
你将依赖于 JavaScript 功能,例如 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
属性。对于列表中的每个项目,你应该传递一个字符串或数字,该字符串或数字在兄弟姐妹中唯一地标识该项目。通常,键应该来自你的数据,例如数据库 ID。React 使用你的键来了解你稍后插入、删除或重新排序项目时发生了什么。
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> ); }
响应事件
你可以通过在组件中声明事件处理程序函数来响应事件。
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
请注意,onClick={handleClick}
末尾没有括号!不要调用事件处理程序函数:你只需要传递它。当用户点击按钮时,React 将调用你的事件处理程序。
更新屏幕
通常,你希望你的组件“记住”一些信息并显示它。例如,也许你想计算按钮被点击的次数。为此,请向你的组件添加状态。
首先,从 React 中导入 useState
import { useState } from 'react';
现在,你可以在组件中声明一个状态变量
function MyButton() {
const [count, setCount] = useState(0);
// ...
你将从 useState
中得到两件事:当前状态 (count
) 以及允许你更新它的函数 (setCount
)。你可以给他们任何名字,但惯例是写 [something, setSomething]
。
按钮第一次显示时,count
将为 0
,因为你将 0
传递给了 useState()
。当你想更改状态时,请调用 setCount()
并将新值传递给它。点击此按钮将增加计数器。
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
React 将再次调用你的组件函数。这次,count
将为 1
。然后它将为 2
。等等。
如果你多次渲染同一个组件,每个组件都将获得自己的状态。分别点击每个按钮。
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> ); }
请注意,每个按钮如何“记住”它自己的 count
状态,并且不会影响其他按钮。
使用 Hook
以 use
开头的函数称为Hook。 useState
是 React 提供的内置 Hook。你可以在 API 参考 中找到其他内置 Hook。你还可以通过组合现有的 Hook 来编写自己的 Hook。
Hook 比其他函数更严格。你只能在组件(或其他 Hook)的顶部调用 Hook。如果你想在条件或循环中使用 useState
,请提取一个新的组件并将其放在那里。
组件之间的数据共享
在前面的例子中,每个 MyButton
都有自己独立的 count
,当每个按钮被点击时,只有被点击的按钮的 count
会发生变化
但是,通常您需要组件来 _共享数据并始终一起更新_。
要使两个 MyButton
组件显示相同的 count
并一起更新,您需要将状态从单个按钮 “向上” 移动到包含所有按钮的最近的组件。
在这个例子中,它是 MyApp
现在,当您单击任一按钮时,count
在 MyApp
中将发生改变,这将改变两个 MyButton
中的计数。以下是您如何在代码中表达这一点。
首先,_将状态向上_ 从 MyButton
移动到 MyApp
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... we're moving code from here ...
}
然后,_将状态向下_ 从 MyApp
传递到每个 MyButton
,以及共享的点击处理程序。您可以使用 JSX 花括号将信息传递给 MyButton
,就像您之前对 <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} />
</div>
);
}
您像这样传递下去的信息被称为 _props_。现在,MyApp
组件包含 count
状态和 handleClick
事件处理程序,并 _将它们都作为 props 传递给_ 每个按钮。
最后,更改 MyButton
来 _读取_ 您从其父组件传递的 props
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
当您单击按钮时,onClick
处理程序会触发。每个按钮的 onClick
prop 都设置为 handleClick
函数,该函数位于 MyApp
中,因此其中的代码会运行。该代码调用 setCount(count + 1)
,从而递增 count
状态变量。新的 count
值作为 prop 传递给每个按钮,因此它们都显示新值。这称为 “将状态向上提升”。通过将状态向上移动,您已在组件之间共享了它。
import { useState } from 'react'; 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> ); }