使用Props显示数据
到前一课为止,如果你要复用你的 <Header />
组件,里面的内容不可改变。
JSX
function Header() {
return <h1>Develop. Preview. Ship.</h1>;
}
function HomePage() {
return (
<div>
<Header />
<Header />
</div>
);
}
但是,如果你想传递不同的文本,或者外部源获取数据变更,而无法更新信息,该怎么办?
常规 HTML 元素具有可用于传递更改这些元素行为信息的属性。
例如,更改 <img>
元素的 src
属性会更改显示的图像。更改 <a>
标签的 href
属性会更改链接的目标。
同样,你可以将值作为属性传递给 React 组件。
这些称为 props
,例如,我们平常操作的按钮
的可能状态有三种:
与 JavaScript 函数类似,你可以设计接受自定义参数的组件,这些参数会更改组件的行为或显示的内容。然后,你可以将这些参数从父组件传递到子组件。
注意:在 React 中,数据沿着组件树向动。这称为单向数据流。而我们后面讲的状态State,则可以作为参数从父组件传递到子组件。
如何使用Props?
在 HomePage
组件中,你可以将自定义 title
prop 传递给 Header
组件,就像传递 HTML 属性一样:
JSX
function HomePage() {
return (
<div>
<Header title="React" />
</div>
);
}
并且 Header
,子组件可以接受这些 props 作为其第一个函数参数:
JSX
function Header(props) {
return <h1>你好</h1>;
}
如果你 console.log()
支持,你可以看到它是一个带有 title 属性的对象。
JSX
function Header(props) {
console.log(props); // { title: "React" }
return <h1>你好</h1>;
}
由于 props 是一个对象,因此可以使用对象解构来显式命名函数参数中的 props 值:
JSX
function Header({ title }) {
console.log(title); // "React"
return <h1>你好</h1>;
}
然后,你可以将 <h1>
标记的内容替换为你的 title 变量。
JSX
function Header({ title }) {
console.log(title);
return <h1>title</h1>;
}
如果你在浏览器中打开文件,你将看到它正在显示实际的单词"title"。这是因为 React 认为你打算将纯文本字符串渲染给 DOM。
你需要一种方法来告诉 React 这是一个 JavaScript 变量。
在 JSX 中使用变量
要使用 title
道具,请添加大括号 {}
。这些是一种特殊的 JSX 语法,允许你直接在 JSX 标记中编写常规 JavaScript。
JSX
function Header({ title }) {
console.log(title);
return <h1>{title}</h1>;
}
你可以将大括号视为当你处于"JSX 领域"时进入"JavaScript 领域"的一种方式。你可以在大括号内添加任何 JavaScript 表达式(计算结果为单个值的内容)。例如:
- 带有点表示法的对象属性:
JSX
function Header(props) {
return <h1>{props.title}</h1>;
}
- 模板字符串:
JSX
function Header({ title }) {
return <h1>{`Cool ${title}`}</h1>;
}
- 函数的返回值:
JSX
function createTitle(title) {
if (title) {
return title;
} else {
return 'Default title';
}
}
function Header({ title }) {
return <h1>{createTitle(title)}</h1>;
}
- 三元运算符
JSX
function Header({ title }) {
return <h1>{title ? title : 'Default Title'}</h1>;
}
你现在可以将任何字符串传给你的 title prop,而且如果你使用三元运算符,你甚至可以快速进行数据判断,并给出默认值:
JSX
function Header({ title }) {
return <h1>{title ? title : 'Default title'}</h1>;
}
function HomePage() {
return (
<div>
<Header />
</div>
);
}
你的组件现在可以使用通用属性 prop,您可以在应用程序的不同部分复用该 prop。您需要做的就是更改属性字符串:
JSX
function HomePage() {
return (
<div>
<Header title="React" />
<Header title="A new title" />
</div>
);
}
遍历列表
通常需要将数据显示为列表。您可以使用数组方法来操作数据并生成样式相同但包含不同信息的 UI 元素。
将以下名称数组添加到组件 HomePage
:
JSX
function HomePage() {
const names = ['张三', '李四', '王五'];
return (
<div>
<Header title="你好" />
</div>
);
}
然后,可以使用该 array.map()
方法循环访问数组,并使用箭头函数将名称映射到列表项:
JSX
function HomePage() {
const names = ['张三', '李四', '王五'];
return (
<div>
<Header title="你好" />
<ul>
{names.map((name) => (
<li>{name}</li>
))}
</ul>
</div>
);
}
请注意,你可以使用大括号在"JavaScript"和"JSX"区域之间进行代码切换。也就是说要在JSX里面使用JavaScript,你得写在{}里面。
现在,如果你运行这段代码,React 会给我们一个关于缺少 key
prop 的警告。这是因为 React 需要一些东西来唯一标识数组中的项,以便它知道要在 DOM 中更新哪些元素。
你现在可以直接把key的值设置为name的值,因为它们当前是唯一的,但建议使用保证唯一的名称,例如项目 ID。
JSX
function HomePage() {
const names = ['张三', '李四', '王五'];
return (
<div>
<Header title="你好" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
</div>
);
}
深入了解React数据传递
使用State添加状态与交互
我们现在来探讨一下 React 如何帮助我们增加状态和事件处理程序的交互性。
例如,让我们在 HomePage
组件中创建一个"赞"按钮。首先,在 return()
语句中添加一个 button 元素:
JSX
function HomePage() {
const names = ['张三', '李四', '王五'];
return (
<div>
<Header title="你好" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<button>Like</button>
</div>
);
}
事件监听
若要使按钮在单击时执行某些操作,可以使用以下 onClick
事件:
javascript
function HomePage() {
// ...
return (
<div>
{/* ... */}
<button onClick={}>Like</button>
</div>
);
}
在 React 中,事件名称是小驼峰格式。该 onClick
事件是可用于响应用户交互的众多事件之一。例如,您可以在Input
中使用 onChange
或在Form
中使用 onSubmit
。
事件绑定
您可以定义一个函数,以便在触发事件时"绑定"事件。在返回语句之前创建一个函数,名为 handleClick()
:
JSX
function HomePage() {
// ...
function handleClick() {
console.log("点赞啦~")
}
return (
<div>
{/* ... */}
<button onClick={}>Like</button>
</div>
)
}
然后,您可以在触发 onClick
事件时调用该 handleClick
函数:
JSX
function HomePage() {
// ...
function handleClick() {
console.log('点赞啦~');
}
return (
<div>
{/* ... */}
<button onClick={handleClick}>Like</button>
</div>
);
}
你现在可以看下运行效果。
状态State和钩子Hooks
React 有一组称为钩子的函数。钩子允许您向组件添加其他逻辑,例如状态。可以将状态视为 UI 中随时间变化的任何信息,通常由用户交互触发。
您可以使用状态来存储和增加用户单击"赞"按钮的次数。事实上,用于管理状态的 React 钩子被称为: useState()
添加到 useState()
您的项目。它返回一个数组,您可以使用数组解构在组件中访问和使用这些数组值:
JSX
function HomePage() {
// ...
const [] = React.useState();
// ...
}
数组中的第一项是 状态 value
,您可以命名任何内容。建议将其命名为描述性名称:
JSX
function HomePage() {
// ...
const [likes] = React.useState();
// ...
}
数组中的第二项是值 update
的函数。您可以将更新函数命名为任何名称,但通常要为其前缀, set
后跟要更新的状态变量的名称:
JSX
function HomePage() {
// ...
const [likes, setLikes] = React.useState();
// ...
}
您还可以借此机会将状态 likes
的初始值添加到 0
:
JSX
function HomePage() {
// ...
const [likes, setLikes] = React.useState(0);
}
然后,您可以使用组件中的状态变量检查初始状态是否正常工作。
javascript
function HomePage() {
// ...
const [likes, setLikes] = React.useState(0);
// ...
return (
// ...
<button onClick={handleClick}>Like({likes})</button>
);
}
最后,你可以调用你的状态更新器函数, setLikes
在你的 HomePage
组件中,让我们把它添加到你之前定义的 handleClick()
函数中:
JSX
function HomePage() {
// ...
const [likes, setLikes] = React.useState(0);
function handleClick() {
setLikes(likes + 1);
}
return (
<div>
{/* ... */}
<button onClick={handleClick}>Likes ({likes})</button>
</div>
);
}
单击该按钮后,会调用该 handleClick
函数,该函数使用当前点赞数 + 1 的参数,去调用状态更新函数 setLikes
。
注意:与作为第一个函数参数传递给组件的 prop 不同,状态是在组件中启动并存储的。您可以将状态信息作为 prop 传递给子组件,但更新状态的逻辑应保留在最初创建状态的组件中。
状态管理
这只是对状态的介绍,你可以了解更多关于在 React 应用程序中管理状态和数据流的知识。要了解更多信息,我们建议您阅读 React 文档中的Adding Interactivity和Managing State部分。
更多状态资源,可以参考
示例代码
到目前为止,我们探讨了如何开始使用 React。下面的代码是最终代码,请将此代码粘贴到代码编辑器中的 index.html
文件中。
JSX
<html>
<body>
<div id="app"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/jsx">
const app = document.getElementById("app")
function Header({ title }) {
return <h1>{title ? title : "Default title"}</h1>
}
function HomePage() {
const names = ['张三', '李四', '王五'];
const [likes, setLikes] = React.useState(0)
function handleClick() {
setLikes(likes + 1)
}
return (
<div>
<Header title="你好" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
<button onClick={handleClick}>Like ({likes})</button>
</div>
)
}
const root = ReactDOM.createRoot(app);
root.render(<HomePage />);
</script>
</body>
</html>
通过003和004,你学习了三个基本的 React 概念:组件、属性props和状态state。在这些方面打下坚实的基础将帮助你开始构建 React 应用程序。
在学习 React 时,最好的学习方式是构建。你可以通过使用 <script>
和你到目前为止所学到的知识来逐步采用 React,将小组件添加到现有网站。
从React到Next.js
虽然 React 擅长构建 UI,但将该 UI 独立构建为功能齐全的可扩展应用程序确实需要一些工作。还有一些较新的 React 功能,如服务器和客户端组件,需要一个框架。
而Next.js 处理了大部分设置和配置,并具有帮助您构建 React 应用程序的附加功能。
接下来,我们将把示例从 React 迁移到 Next.js,讨论Next.js的工作原理,并向您介绍服务器和客户端组件之间的区别。