作者选择Creative Commons接受捐赠,作为Write for DOnations计划的一部分。
介绍
在本教程中,您将使用React JavaScript 库创建带有 props 的包装器组件。包装组件是围绕未知组件并提供默认结构来显示子组件的组件。此模式可用于创建在整个设计中重复使用的用户界面 (UI) 元素,例如模态、模板页面和信息图块。
要创建包装器组件,您将首先学习使用rest 和 spread 运算符来收集未使用的 props 以传递给嵌套组件。然后,您将创建一个组件,该组件使用内置children
组件将嵌套组件包装在JSX 中,就像它们是HTML元素一样。最后,您将组件作为 props 传递以创建灵活的包装器,这些包装器可以在一个组件的多个位置嵌入自定义 JSX。
在本教程中,您将构建组件以以卡片的形式显示动物数据列表。在创建灵活的包装组件时,您将学习拆分数据和重构组件。在本教程结束时,您将拥有一个工作应用程序,该应用程序将使用高级 prop 技术创建可重用组件,这些组件将随着应用程序的增长和变化而扩展和适应。
注意:第一步设置一个空白项目,您将在该项目上构建教程练习。如果您已经有一个工作项目并想直接使用 props,请从第 2 步开始。
先决条件
-
你需要一个运行Node.js的开发环境;本教程在 Node.js 版本 10.20.1 和 npm 版本 6.14.4 上进行了测试。要在 macOS 或 Ubuntu 18.04 上安装它,请按照如何在 macOS 上安装 Node.js 和创建本地开发环境或如何在 Ubuntu 18.04 上安装 Node.js 的使用 PPA 安装部分中的步骤进行操作。
-
在本教程中,您将使用Create React App创建一个应用程序。您可以在如何使用 Create React App 设置 React 项目中找到有关使用 Create React App 安装应用程序的说明以及有关其工作原理的一般信息。
-
您将使用 React 组件,您可以在我们的如何在 React教程中创建自定义组件中了解。它还有助于对 React props 有基本的了解,您可以在如何使用 Props 自定义 React 组件中了解这些内容。
-
您还需要具备 JavaScript 的基本知识(可以在我们的“如何使用 JavaScript 编码”系列中找到)以及 HTML 和 CSS 的基本知识。关于 HTML 和 CSS 的一个很好的资源是Mozilla Developer Network。
第 1 步 – 创建一个空项目
在这一步中,您将使用Create React App创建一个新项目。然后,您将删除引导项目时安装的示例项目和相关文件。最后,您将创建一个简单的文件结构来组织您的组件。这将为您在下一步中构建本教程的包装器应用程序提供坚实的基础。
首先,创建一个新项目。在命令行中,运行以下脚本以使用以下命令安装新项目create-react-app
:
- npx create-react-app wrapper-tutorial
项目完成后,切换到目录:
- cd wrapper-tutorial
在新的终端选项卡或窗口中,使用Create React App start script启动项目。浏览器将自动刷新更改,因此在您工作时保持此脚本运行:
- npm start
您将获得一个正在运行的本地服务器。如果项目没有在浏览器窗口中打开,您可以使用http://localhost:3000/
. 如果您从远程服务器运行它,则地址将为.http://your_domain:3000
您的浏览器将加载一个简单的 React 应用程序,该应用程序包含在 Create React App 中:
您将构建一组全新的自定义组件,因此您需要先清除一些样板代码,以便您可以拥有一个空项目。
首先,src/App.js
在文本编辑器中打开。这是注入页面的根组件。所有组件将从这里开始。您可以App.js
在如何使用 Create React App 设置 React 项目中找到更多信息。
src/App.js
使用以下命令打开:
- nano src/App.js
你会看到一个这样的文件:
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
删除该行import logo from './logo.svg';
。然后替换return
语句中的所有内容以返回一组空标签:<></>
。这将为您提供一个不返回任何内容的有效页面。最终代码将如下所示:
import React from 'react';
import './App.css';
function App() {
return <></>;
}
export default App;
保存并退出文本编辑器。
最后,删除标志。您不会在您的应用程序中使用它,您应该在工作时删除未使用的文件。从长远来看,这将使您免于困惑。
在终端窗口中输入以下命令:
- rm src/logo.svg
如果您查看浏览器,您将看到一个空白屏幕。
现在您已经清除了示例 Create React App 项目,创建一个简单的文件结构。这将帮助您保持组件隔离和独立。
在目录components
中创建一个名为的src
目录。这将容纳您所有的自定义组件。
- mkdir src/components
每个组件都有自己的目录来存储组件文件以及样式、图像(如果有的话)和测试。
创建一个目录App
:
- mkdir src/components/App
将所有App
文件移动到该目录中。使用通配符 ,*
选择以不App.
考虑文件扩展名开头的任何文件。然后使用mv
命令将它们放入新目录:
- mv src/App.* src/components/App
接下来,更新 中的相对导入路径index.js
,它是引导整个过程的根组件:
- nano src/index.js
import 语句需要指向目录App.js
中的App
文件,因此进行以下突出显示的更改:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
保存并退出文件。
现在项目已设置,您可以创建您的第一个组件。
第 2 步 – 收集未使用的道具 ...props
在这一步中,您将创建一个组件来显示关于一组动物的一组数据。您的组件将包含第二个嵌套组件以直观地显示一些信息。要连接父组件和嵌套组件,您将使用rest 和 spread 运算符将未使用的道具从父级传递给子级,而父级无需知道道具的名称或类型。
在这一步结束时,您将拥有一个父组件,它可以为嵌套组件提供 props,而无需知道 props 是什么。这将保持父组件的灵活性,允许您更新子组件而无需更改父组件。
创建AnimalCard
组件
首先,为您的动物创建一组数据。首先,打开一个包含components/App
目录中数据集的文件:
- nano src/components/App/data.js
添加以下数据:
export default [
{
name: 'Lion',
scientificName: 'Panthero leo',
size: 140,
diet: ['meat']
},
{
name: 'Gorilla',
scientificName: 'Gorilla beringei',
size: 205,
diet: ['plants', 'insects']
},
{
name: 'Zebra',
scientificName: 'Equus quagga',
size: 322,
diet: ['plants'],
}
]
动物的这份名单是一个数组的对象,其中包括动物的名称,学名,体重和饮食。
保存并关闭文件。
接下来,为AnimalCard
组件创建一个目录:
- mkdir src/components/AnimalCard
在目录中打开一个新文件:
- nano src/components/AnimalCard/AnimalCard.js
现在添加一个组件,它会采取name
,diet
以及size
为道具,并显示它:
import React from 'react';
import PropTypes from 'prop-types';
export default function AnimalCard({ diet, name, size }) {
return(
<div>
<h3>{name}</h3>
<div>{size}kg</div>
<div>{diet.join(', ')}.</div>
</div>
)
}
AnimalCard.propTypes = {
diet: PropTypes.arrayOf(PropTypes.string).isRequired,
name: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
}
在这里,您正在解构函数参数列表中的道具AnimalCard
,然后在div
. diet
使用join()
方法将数据列为单个字符串。每条数据都包含一个对应PropType
的数据,以确保数据类型正确。
保存并关闭文件。
现在您有了组件和数据,您需要将它们组合在一起。要做到这一点,进口的组件和数据到项目的根组件:App.js
。
首先,打开组件:
- nano src/components/App/App.js
从那里,您可以遍历数据并返回AnimalCard
带有相关道具的新数据。将突出显示的行添加到App.js
:
import React from 'react';
import './App.css';
import animals from './data';
import AnimalCard from '../AnimalCard/AnimalCard';
function App() {
return (
<div className="wrapper">
{animals.map(animal =>
<AnimalCard
diet={animal.diet}
key={animal.name}
name={animal.name}
size={animal.size}
/>
)}
</div>
);
}
export default App;
保存并关闭文件。
当你在更复杂的项目,获得的数据将来自于更加多样化的地方,如API的,localStorage
或静态文件。但是使用这些的过程是相似的:将数据分配给一个变量并遍历数据。在这种情况下,数据来自静态文件,因此您直接导入到变量中。
在此代码中,您使用.map()
方法迭代animals
并显示道具。请注意,您不必使用每条数据。例如,您没有明确传递scientificName
属性。您还添加了一个单独的key
prop,React 将使用它来跟踪映射的数据。最后,你是一个包装的代码div
用className
的wrapper
,你会用它来添加一些造型。
要添加此样式,请打开App.css
:
- nano src/components/App/App.css
删除样板样式并将flex 属性添加到名为 的类wrapper
:
.wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 20px;
}
这将使用 flexbox 布局来组织数据,使其对齐。padding
在浏览器窗口中留出一些空间,并justify-content
在元素之间展开额外的空间。
保存并退出文件。当你这样做时,浏览器将刷新,你会看到一些数据间隔。
创建详细信息组件
您现在有一个显示数据的简单组件。但是,假设您想diet
通过将文本转换为表情符号来为数据添加一些风格。您可以通过转换组件中的数据来做到这一点。
React 被设计为灵活的,所以当你考虑如何转换数据时,你有几个不同的选择:
- 您可以在组件内创建一个将文本转换为表情符号的函数。
- 您可以创建一个函数并将其存储在组件外部的文件中,以便您可以在不同的组件之间重用逻辑。
- 您可以创建一个单独的组件,将文本转换为表情符号。
当应用于正确的用例时,每种方法都很好,并且在构建应用程序时,您会发现自己在它们之间切换。为了避免过早的抽象和复杂性,您应该使用第一个选项开始。如果您发现自己想要重用逻辑,则可以将函数从组件中单独拉出。如果您想要一个包含逻辑和标记的可重用部分,或者您想要隔离以在整个应用程序中使用,则第三个选项是最佳选择。
在这种情况下,我们将创建一个新组件,因为我们稍后会想要添加更多数据,并且我们将标记与转换逻辑相结合。
新组件将被调用AnimalDetails
。为此,请创建一个新目录:
- mkdir src/components/AnimalDetails
接下来,AnimalDetails.js
在文本编辑器中打开:
- nano src/components/AnimalDetails/AnimalDetails.js
在文件中,制作一个小组件,将 显示diet
为表情符号:
import React from 'react';
import PropTypes from 'prop-types';
import './AnimalDetails.css';
function convertFood(food) {
switch(food) {
case 'insects':
return '🐜';
case 'meat':
return '🍖';
case 'plants':
default:
return '🌱';
}
}
export default function AnimalDetails({ diet }) {
return(
<div className="details">
<h4>Details:</h4>
<div>
Diet: {diet.map(food => convertFood(food)).join(' ')}
</div>
</div>
)
}
AnimalDetails.propTypes = {
diet: PropTypes.arrayOf(PropTypes.string).isRequired,
}
该AnimalDetails.propTypes
对象设置函数以获取一个diet
字符串数组的属性。然后在组件内部,代码循环遍历diet
并使用switch语句将字符串转换为表情符号。
保存并关闭文件。
您还导入了一些 CSS,所以现在让我们添加它。
打开AnimalDetails.css
:
- nano src/components/AnimalDetails/AnimalDetails.css
添加一些 CSS 为元素提供边框和边距,以将细节与组件的其余部分分开:
.details {
border-top: gray solid 1px;
margin: 20px 0;
}
我们.details
用来将规则与 a className
of 的元素进行匹配details
。
保存并关闭文件。
现在您有了一个新的自定义组件,您可以将它添加到您的AnimalCard
组件中。打开AnimalCard.js
:
- nano src/components/AnimalCard/AnimalCard.js
用diet.join
新AnimalDetails
组件替换该语句并通过diet
添加突出显示的行作为道具传递:
import React from 'react';
import PropTypes from 'prop-types';
import AnimalDetails from '../AnimalDetails/AnimalDetails';
export default function AnimalCard({ diet, name, size }) {
return(
<div>
<h3>{name}</h3>
<div>{size}kg</div>
<AnimalDetails
diet={diet}
/>
</div>
)
}
AnimalCard.propTypes = {
diet: PropTypes.arrayOf(PropTypes.string).isRequired,
name: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
}
保存文件,您将在浏览器中看到新的详细信息。
通过组件传递细节 ...props
这些组件可以很好地协同工作,但AnimalCard
. 您明确地diet
退出了props
论点,但您没有使用数据。相反,您将它传递给组件。这并没有本质上的错误——事实上,在过多的沟通方面犯错通常会更好。但是这样做会使您的代码更难以维护。每当要向 传递新数据时AnimalDetails
,都需要更新三个地方:App
,传递道具的地方,AnimalDetails
消耗道具的 ,以及中间人的AnimalCard
。
更好的方法是将所有未使用的道具收集在里面AnimalCard
,然后将它们直接传递给AnimalDetails
. 这使您有机会在AnimalDetails
不更改的情况下进行更改AnimalCard
。实际上,AnimalCard
不需要知道任何关于 props 或PropTypes
进入AnimalDetails
.
为此,您将使用对象休息运算符。此运算符收集在解构过程中未拉出的所有项目,并将它们保存到一个新对象中。
这是一个简单的例子:
const dog = {
name: 'dog',
diet: ['meat']
}
const { name, ...props } = dog;
在这种情况下,变量name
将为'dog'
,变量props
将为{ diet: ['meat']}
。
到目前为止,您已经将所有 props 当作 HTML 属性来传递,但是您也可以使用对象来发送 props。要将对象用作道具,您需要使用展开运算符...props
——用花括号括起来。这会将每个键值对更改为一个 prop。
打开AnimalCard.js
:
- nano src/components/AnimalCard/AnimalCard.js
在里面,diet
从解构的对象中移除,而是将其余的道具收集到一个名为 的变量中props
。然后将这些道具直接传递给AnimalDetails
:
import React from 'react';
import PropTypes from 'prop-types';
import AnimalDetails from '../AnimalDetails/AnimalDetails';
export default function AnimalCard({ name, size, ...props }) {
return(
<div>
<h3>{name}</h3>
<div>{size}kg</div>
<AnimalDetails
{...props}
/>
</div>
)
}
AnimalCard.propTypes = {
name: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
}
请注意,您可以删除 ,diet
PropType
因为您没有在此组件中使用该道具。
在这种情况下,您只将一个道具传递给AnimalDetails
. 如果您有多个道具,则顺序很重要。较晚的道具会覆盖较早的道具,因此如果您有要优先使用的道具,请确保它位于最后。如果您的props
对象具有也是命名值的属性,这可能会导致一些混淆。
保存并关闭文件。浏览器将刷新,一切看起来都一样:
怎么看...props
对象增加了灵活性,让我们通过scientificName
对AnimalDetails
通过AnimalCard
组件。
首先,打开App.js
:
- nano src/components/App/App.js
然后将其scientificName
作为道具传递:
import React from 'react';
import './App.css';
import animals from './data';
import AnimalCard from '../AnimalCard/AnimalCard';
function App() {
return (
<div className="wrapper">
{animals.map(animal =>
<AnimalCard
diet={animal.diet}
key={animal.name}
name={animal.name}
size={animal.size}
scientificName={animal.scientificName}
/>
)}
</div>
);
}
export default App;
保存并关闭文件。
跳过AnimalCard
; 您无需在那里进行任何更改。然后打开,AnimalDetails
以便您可以使用新道具:
- nano src/components/AnimalDetails/AnimalDetails.js
新的 prop 将是一个字符串,您将把它details
与声明以下内容的行一起添加到列表中PropType
:
import React from 'react';
...
export default function AnimalDetails({ diet, scientificName }) {
return(
<div className="details">
<h4>Details:</h4>
<div>
Scientific Name: {scientificName}.
</div>
<div>
Diet: {diet.map(food => convertFood(food)).join(' ')}
</div>
</div>
)
}
AnimalDetails.propTypes = {
diet: PropTypes.arrayOf(PropTypes.string).isRequired,
scientificName: PropTypes.string.isRequired,
}
保存并关闭文件。当您这样做时,浏览器将刷新,您将看到新的详细信息,而不会对AnimalCard
组件进行任何更改:
在这一步中,您学习了如何创建灵活的父 props,这些 props 可以接受未知的 props 并使用扩展运算符将它们传递到嵌套组件中。这是一种常见的模式,它将为您提供创建具有重点职责的组件所需的灵活性。在下一步中,您将使用内置children
prop创建可以将未知组件作为 prop 的组件。
第 3 步 – 创建包装组件 children
在这一步中,您将创建一个包装器组件,它可以将一组未知的组件作为道具。这将使您能够嵌套诸如标准 HTML 之类的组件,并为您提供一种创建可重用包装器的模式,使您可以制作需要通用设计但内部灵活的各种组件。
React 为您提供了一个名为的内置道具children
,用于收集任何子组件。使用它使创建包装器组件变得直观和可读。
首先,创建一个名为Card
. 这将是一个包装组件,用于为任何新的卡片组件创建标准样式。
创建一个新目录:
- mkdir src/components/Card
然后Card
在文本编辑器中打开组件:
- nano src/components/Card/Card.js
通过添加以下代码,创建一个将children
和title
作为道具并将它们包装在 a 中的组件div
:
import React from 'react';
import PropTypes from 'prop-types';
import './Card.css';
export default function Card({ children, title }) {
return(
<div className="card">
<div className="card-details">
<h2>{title}</h2>
</div>
{children}
</div>
)
}
Card.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element.isRequired
]),
title: PropTypes.string.isRequired,
}
在PropTypes
为children
是新的。所述children
支柱可以是一个JSX元件或JSX元件的阵列。该title
是一个字符串。
保存并关闭文件。
接下来,添加一些样式。打开Card.css
:
- nano src/components/Card/Card.css
您的卡片将在详细信息下方有一个边框和一条线。
.card {
border: black solid 1px;
margin: 10px;
padding: 10px;
width: 200px;
}
.card-details {
border-bottom: gray solid 1px;
margin-bottom: 20px;
}
保存并关闭文件。现在您拥有了您的组件,您需要使用它。您可以AnimalCard
使用 中的Card
组件将每个包裹起来App.js
,但由于名称AnimalCard
暗示它已经是Card
,因此最好使用 中的Card
组件AnimalCard
。
打开AnimalCard
:
- nano src/components/AnimalCard/AnimalCard.js
与其他 props 不同,您不会children
显式传递。相反,您将 JSX 包含为 HTML 子元素。换句话说,您只需将它们嵌套在元素内,如下所示:
import React from 'react';
import PropTypes from 'prop-types';
import Card from '../Card/Card';
import AnimalDetails from '../AnimalDetails/AnimalDetails';
export default function AnimalCard({ name, size, ...props }) {
return(
<Card title="Animal">
<h3>{name}</h3>
<div>{size}kg</div>
<AnimalDetails
{...props}
/>
</Card>
)
}
AnimalCard.propTypes = {
name: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
}
与 React 组件不同,您不需要将单个根元素作为子元素。这就是为什么PropType
forCard
指定它可以是元素数组或单个元素。除了传递children
as 嵌套组件之外,您还为卡片指定了Animal
.
保存并关闭文件。当您这样做时,浏览器将刷新,您将看到更新的卡片组件。
现在您有了一个可重用的Card
组件,它可以包含任意数量的嵌套子组件。这样做的主要优点是您可以将其Card
与任何任意组件重用。如果你想制作一张Plant
卡片,你可以通过用Card
组件包装植物信息来实现。它甚至根本不需要关联:如果您想Card
在列出音乐或帐户数据等内容的完全不同的应用程序中重用该组件,您也可以这样做。该Card
组件不关心孩子是什么;您只是重复使用包装元素,在这种情况下是样式边框和标题。
使用的缺点children
是您只能拥有一个子道具实例。有时,您会希望组件在多个位置具有自定义 JSX。幸运的是,您可以通过将 JSX 和 React 组件作为 props 传递来做到这一点,我们将在下一步中介绍。
第 4 步——将组件作为 props 传递
在这一步中,您将修改您的Card
组件以将其他组件作为道具。这将使您的组件具有最大的灵活性,可以在整个页面的多个位置显示未知组件或 JSX。与children
您只能使用一次的 不同,您可以拥有与 props 一样多的组件,让您的包装组件能够适应各种需求,同时保持标准的外观和结构。
在这一步结束时,您将拥有一个可以包装子组件并在卡片中显示其他组件的组件。当您需要创建需要比简单字符串和整数更复杂的信息的组件时,此模式将为您提供灵活性。
让我们修改Card
组件以获取一个名为 的任意 React 元素details
。
首先,打开Card
组件:
- nano src/components/Card/Card.js
接下来,添加一个名为的新道具details
并将其放置在<h2>
元素下方:
import React from 'react';
import PropTypes from 'prop-types';
import './Card.css';
export default function Card({ children, details, title }) {
return(
<div className="card">
<div className="card-details">
<h2>{title}</h2>
{details}
</div>
{children}
</div>
)
}
Card.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.element),
PropTypes.element.isRequired
]),
details: PropTypes.element,
title: PropTypes.string.isRequired,
}
Card.defaultProps = {
details: null,
}
此道具将具有与 相同的类型children
,但它应该是可选的。要使其成为可选,您添加了一个默认值null
。在这种情况下,如果用户没有传递任何细节,组件仍然有效并且不会显示任何额外内容。
保存并关闭文件。页面将刷新,您将看到与之前相同的图像:
现在添加一些细节到AnimalCard
. 首先,打开AnimalCard
.
- nano src/components/AnimalCard/AnimalCard.js
由于该Card
组件已经在使用children
,您需要将新的 JSX 组件作为 prop 传递。由于这些都是哺乳动物,请将其添加到卡片中,但将其包裹在<em>
标签中使其成为斜体。
import React from 'react';
...
export default function AnimalCard({ name, size, ...props }) {
return(
<Card title="Animal" details={<em>Mammal</em>}>
<h3>{name}</h3>
<div>{size}kg</div>
<AnimalDetails
{...props}
/>
</Card>
)
}
...
保存文件。当您这样做时,浏览器将刷新,您将看到更新,包括短语Mammal。
这个 prop 已经很强大了,因为它可以接受任何大小的 JSX。在本例中,您只添加了一个元素,但您可以根据需要传递尽可能多的 JSX。它也不必是 JSX。例如,如果你有一个复杂的标记,你不会想直接在 prop 中传递它;这将很难阅读。相反,您可以创建一个单独的组件,然后将该组件作为 prop 传递。
要在工作中看到这一点,请传递AnimalDetails
给details
道具:
import React from 'react';
...
export default function AnimalCard({ name, size, ...props }) {
return(
<Card
title="Animal"
details={
<AnimalDetails
{...props}
/>
}
>
<h3>{name}</h3>
<div>{size}kg</div>
</Card>
)
}
...
AnimalDetails
更复杂,并且有许多标记行。如果直接将其添加到 中details
,则会大大增加道具并使其难以阅读。
保存并关闭文件。执行此操作后,浏览器将刷新,详细信息将显示在卡片顶部。
现在你有了一个Card
可以接受自定义 JSX 并将其放置在多个位置的组件。您不仅限于单个道具;您可以根据需要将元素传递给任意数量的道具。这使您能够创建灵活的包装组件,让其他开发人员有机会自定义组件,同时保留其整体样式和功能。
将组件作为道具传递并不完美。它有点难以阅读,不像 pass 那样清晰children
,但它们同样灵活,您可以在组件中使用任意数量的它们。您应该children
首先使用,但如果这还不够,请不要犹豫退回到道具。
在这一步中,您学习了如何将 JSX 和 React 组件作为 props 传递给另一个组件。这将使您的组件能够灵活地处理许多情况,其中包装器组件可能需要多个 props 来处理 JSX 或组件。
结论
您已经创建了各种包装组件,可以灵活地显示数据,同时保持可预测的外观和结构。您创建了可以收集未知道具并将其传递给嵌套组件的组件。您还使用内置children
prop 创建了可以处理任意数量嵌套元素的包装器组件。最后,您创建了一个可以将 JSX 或 React 组件作为道具的组件,以便您的包装器组件可以处理不同定制的多个实例。
包装组件使您能够适应未知环境,同时最大限度地提高代码重用性和一致性。此模式可用于创建您将在整个应用程序中重复使用的基本 UI 元素,包括:按钮、警报、模式、幻灯片等。你会发现自己多次回到它。
如果您想查看更多 React 教程,请查看我们的React 主题页面,或返回如何在 React.js 系列中编码页面。