如何使用道具在 React 中创建封装组件

作者选择了 Creative Commons以作为 Write for Donations计划的一部分获得捐赠。

介绍

在本教程中,您将使用 React JavaScript 库创建附件组件。 Wrapper components 是围绕未知组件的组件,并提供默认结构来显示子组件的组件。

要创建包装组件,您首先将学习如何使用 休息和扩散操作员来收集未使用的附件,以便将其传递到嵌入式组件中。 然后,您将创建一个组件,该组件使用内置的孩子组件将嵌入式组件嵌入到 JSX 仿佛它们是 HTML 元素。

在教程中,您将构建组件以显示卡的形式的动物数据列表,您将学习如何分割数据和重塑器组件,当您创建灵活的包装组件。

<$>[注] :第一个步骤设置了一个空白的项目,你将建立教程的练习. 如果你已经有一个工作项目,并想直接进入与奖励工作,开始与 ** Step 2**

前提条件

  • 联合国 您需要运行一个开发环境 [Node.js] (https://nodejs.org/en/about/); 此教程在Node.js 版本10.20.1和npm 版本6.14.4. 上进行了测试. 要在 macOS 或 Ubuntu 18.04 上安装此功能,请遵循 [如何在 macOS (https://andsky.com/tech/tutorials/how-to-install-node-js-and-create-a-local-development-environment-on-macos 上安装节点并创建本地开发环境] 或 [如何在 Ubuntu 18.04 (https://andsky.com/tech/tutorials/how-to-install-node-js-on-ubuntu-18-04# installing-using-a-ppa 上安装节点.js] 的 ** 部分使用 PPA** 。
  • 联合国 在此教程中, 您将创建一个应用 : [Create React App] (https://github.com/facebook/create-react-app) 。 您可以在 [How To Set Up up a React Project with Create React App] (https://andsky.com/tech/tutorials/how-to-set-up-a-react-project-with-create-react-app]] 上找到安装应用程序的指令和关于它如何工作的一般信息.
  • 联合国 您将使用 React 组件, 您可以在 [如何创建自定义组件 in React] ([ LINK5] ) 教程中了解 。 这也将有助于对反应道具有一个基本的理解,你可以在如何自定义带有道具的反应组件中学习.
  • 联合国 您还需要 JavaScript 的基本知识, 您可以在 [How To Code in JavaScript (https://www.digitalocean.com/community/tutorial_series/how-to-code-in-javascript) 系列中找到, 同时您还需要 HTML 和 CSS 的基本知识 。 HTML和CSS的好资源是Mozilla开发者网络. .

第1步:创建一个空的项目

在此步骤中,您将使用 [Create React App] 创建一个新项目(https://github.com/facebook/create-react-app)。然后您将删除在启动项目时安装的样本项目和相关文件。最后,您将创建一个简单的文件结构来组织您的组件。

在命令行中,运行以下脚本以使用Create-react-app安装新项目:

1npx create-react-app wrapper-tutorial

项目完成后,更改到目录:

1cd wrapper-tutorial

在新的终端卡或窗口中,使用 Create React App start script启动项目。

1npm start

如果项目未在浏览器窗口中打开,您可以使用 http://localhost:3000/ 打开它。 如果您正在从远程服务器运行,则地址将是 http://your_domain:3000

您的浏览器将加载一个简单的 React 应用程序,作为 Create React 应用程序的一部分:

React template project

您将构建一组全新的自定义组件,因此您需要从清除一些锅炉板代码开始,以便您可以有一个空的项目。

要开始,请在文本编辑器中打开src/App.js。 这是注入到页面的根组件。 所有组件将从这里开始。 您可以找到有关App.js的更多信息,请参阅How To Set Up a React Project with Create React App(如何使用Create React App设置反应项目(LINK0))。

使用以下命令打开src/App.js:

1nano src/App.js

你會看到這樣的檔案:

 1[label wrapper-tutorial/src/App.js]
 2import React from 'react';
 3import logo from './logo.svg';
 4import './App.css';
 5
 6function App() {
 7  return (
 8    <div className="App">
 9      <header className="App-header">
10        <img src={logo} className="App-logo" alt="logo" />
11        <p>
12          Edit <code>src/App.js</code> and save to reload.
13        </p>
14        <a
15          className="App-link"
16          href="https://reactjs.org"
17          target="_blank"
18          rel="noopener noreferrer"
19        >
20          Learn React
21        </a>
22      </header>
23    </div>
24  );
25}
26
27export default App;

删除./logo.svg导入标签行,然后更换返回声明中的所有内容,以返回一组空标签:<></>

 1[label wrapper-tutorial/src/App.js]
 2
 3import React from 'react';
 4import './App.css';
 5
 6function App() {
 7  return <></>;
 8}
 9
10export default App;

保存和退出文本编辑器。

最后,删除标志. 你不会在你的应用程序中使用它,你应该在工作时删除未使用的文件。

在终端窗口中,输入以下命令:

1rm src/logo.svg

如果你看你的浏览器,你会看到一个空白的屏幕。

blank screen in chrome

现在您已经清理了 Create React App 样本项目,创建一个简单的文件结构,这将有助于保持您的组件隔离和独立。

src目录中创建一个名为components的目录,这将使您所有的自定义组件都保持在内。

1mkdir src/components

每个组件将有自己的目录来存储组件文件,以及风格,如果有,图像和测试。

创建一个App目录:

1mkdir src/components/App

将所有应用文件移动到该目录中。 使用 wildcard,以选择任何开始于应用的文件,无论文件的扩展,然后使用mv命令将其放入新目录:

1mv src/App.* src/components/App

接下来,更新index.js中的相对导入路径,这是启动整个过程的根组件:

1nano src/index.js

导入声明需要指向应用程序目录中的App.js文件,所以请做出以下突出更改:

 1[label wrapper-tutorial/src/index.js]
 2import React from 'react';
 3import ReactDOM from 'react-dom';
 4import './index.css';
 5import App from './components/App/App';
 6import * as serviceWorker from './serviceWorker';
 7
 8ReactDOM.render(
 9  <React.StrictMode>
10    <App />
11  </React.StrictMode>,
12  document.getElementById('root')
13);
14
15// If you want your app to work offline and load faster, you can change
16// unregister() to register() below. Note this comes with some pitfalls.
17// Learn more about service workers: https://bit.ly/CRA-PWA
18serviceWorker.unregister();

保存和退出文件。

现在项目已经设置,您可以创建您的第一个组件。

步骤 2 — 收集未使用的附件与...附件

在此步骤中,您将创建一个组件来显示一组关于一组动物的数据。 您的组件将包含第二个嵌套组件,以便视觉上显示一些信息。 为了连接父母和嵌套组件,您将使用 休息和扩散操作员将未使用的附件从父母传递给孩子,而无需让父母知道附件的名称或类型。

到此步骤结束时,您将有一个家长组件,可以为嵌入的组件提供补贴,而无需知道补贴是什么。

创建一个动物卡组件

首先,在组件/应用目录中打开包含数据集的文件:

1nano src/components/App/data.js

添加以下数据:

 1[label src/components/App/data.js]
 2
 3export default [
 4  {
 5    name: 'Lion',
 6    scientificName: 'Panthero leo',
 7    size: 140,
 8    diet: ['meat']
 9  },
10  {
11    name: 'Gorilla',
12    scientificName: 'Gorilla beringei',
13    size: 205,
14    diet: ['plants', 'insects']
15  },
16  {
17    name: 'Zebra',
18    scientificName: 'Equus quagga',
19    size: 322,
20    diet: ['plants'],
21  }
22]

这个动物列表是一个(https://andsky.com/tech/tutorials/understanding-arrays-in-javascript)的(https://andsky.com/tech/tutorials/understanding-objects-in-javascript)组合,其中包括动物的名字,科学名称,体重和饮食。

保存并关闭文件。

接下来,为AnimalCard组件创建一个目录:

1mkdir src/components/AnimalCard

在直播中打开新文件:

1nano src/components/AnimalCard/AnimalCard.js

现在,添加一个将名称饮食尺寸作为支撑的组件,并显示它:

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4
 5export default function AnimalCard({ diet, name, size }) {
 6  return(
 7    <div>
 8      <h3>{name}</h3>
 9      <div>{size}kg</div>
10      <div>{diet.join(', ')}.</div>
11    </div>
12  )
13}
14
15AnimalCard.propTypes = {
16  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
17  name: PropTypes.string.isRequired,
18  size: PropTypes.number.isRequired,
19}

在这里,您正在(https://andsky.com/tech/tutorials/understanding-destructuring-rest-parameters-and-spread-syntax-in-javascript)为AnimalCard函数的参数列表中破构(https://andsky.com/tech/tutorials/understanding-destructuring-rest-parameters-and-spread-syntax-in-javascript),然后将数据显示在div中。

保存并关闭文件。

现在你有组件和数据,你需要将它们合并在一起. 要做到这一点,请将组件和数据导入到项目的根组件中: App.js

首先,打开组件:

1nano src/components/App/App.js

从那里,你可以循环数据,并返回一个新的AnimalCard与相关奖励。

 1[label wrapper-tutorial/src/components/App/App.js]
 2import React from 'react';
 3import './App.css';
 4
 5import animals from './data';
 6import AnimalCard from '../AnimalCard/AnimalCard';
 7
 8function App() {
 9  return (
10    <div className="wrapper">
11      {animals.map(animal =>
12        <AnimalCard
13          diet={animal.diet}
14          key={animal.name}
15          name={animal.name}
16          size={animal.size}
17        />
18      )}
19    </div>
20  );
21}
22
23export default App;

保存并关闭文件。

随着您在更复杂的项目上工作,您的数据将来自更为多样化的位置,例如 API, localStorage或静态文件。

在这个代码中,你使用了 [.map()](https://andsky.com/tech/tutorials/how-to-use-array-methods-in-javascript-iteration-methods#map()的方法来重复动物并显示特性。 请注意,你不必使用每个数据。 例如,你没有明确地通过scientificName属性。 您还添加了一个单独的钥匙特性,React将使用它来跟踪(https://andsky.com/tech/tutorials/how-to-create-react-elements-with-jsx# step-4-%E2%80%94-mapping-over-data-to-create-elements)。 最后,你将代码包装成一个div和一个classNamewrapper,你将使用它来添加一些风格。

要添加此样式,请打开App.css:

1nano src/components/App/App.css

移除锅炉板的样式,并将 灵活属性添加到一个名为包装器的类:

1[label prop-tutorial/src/components/App/App.css]
2.wrapper {
3    display: flex;
4    flex-wrap: wrap;
5    justify-content: space-between;
6    padding: 20px;
7}

这将使用 flexbox 布局来组织数据,以便将其排列起来。 padding' 会给浏览器窗口一些空间,而 justify-content' 会分散元素之间的额外空间。

保存和退出文件. 当你这样做时,浏览器将更新,你会看到一些数据间隔。

Browser with data spaced out

创建一个细节组件

现在你有一个简单的组件显示数据,但假设你想通过将文本转换为情感符来给饮食数据一点点风格。

React 的设计是灵活的,所以当你考虑如何转换数据时,你有几种不同的选择:

  • 您可以在组件内创建一个函数,将文本转换为情感符。 * 您可以创建一个函数并将其存储在组件外的文件中,以便在不同组件中重复使用逻辑符号。 * 您可以创建一个独立的组件,将文本转换为情感符号。

每个方法都很好,当应用到正确的使用案例时,你会发现自己在构建应用程序时在它们之间切换。为了避免过早的抽象和复杂性,你应该使用第一个选项开始。

在这种情况下,我们将创建一个新的组件,因为我们将在以后添加更多的数据,我们将标记与转换逻辑相结合。

新的组件将被称为动物细节,然后创建一个新目录:

1mkdir src/components/AnimalDetails

接下来,在文本编辑器中打开AnimalDetails.js:

1nano src/components/AnimalDetails/AnimalDetails.js

在文件中,创建一个小组件,显示饮食作为一个情感符:

 1[label wrapper-tutorial/src/components/AnimalDetails/AnimalDetails.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import './AnimalDetails.css';
 5
 6function convertFood(food) {
 7  switch(food) {
 8    case 'insects':
 9      return '🐜';
10    case 'meat':
11      return '🍖';
12    case 'plants':
13    default:
14      return '🌱';
15  }
16}
17
18export default function AnimalDetails({ diet }) {
19  return(
20    <div className="details">
21      <h4>Details:</h4>
22      <div>
23        Diet: {diet.map(food => convertFood(food)).join(' ')}
24      </div>
25    </div>
26  )
27}
28
29AnimalDetails.propTypes = {
30  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
31}

AnimalDetails.propTypes对象设置了一个函数来取代饮食这个字符串的数组,然后在组件内部,代码循环在饮食上,并使用 switch语句将这个字符串转换成一个情感符号。

保存并关闭文件。

你也正在导入一些CSS,所以让我们现在添加它。

打开动物细节.css:

1nano src/components/AnimalDetails/AnimalDetails.css

添加一些 CSS 以给元素一个边界和边界来将细节与其他元素分离:

1[label wrapper-tutorial/src/components/AnimalDetails/AnimalDetails.css]
2.details {
3    border-top: gray solid 1px;
4    margin: 20px 0;
5}

我们使用.details来匹配规则与detailsclassName元素。

保存并关闭文件。

现在你有一个新的自定义组件,你可以将其添加到你的AnimalCard组件。

1nano src/components/AnimalCard/AnimalCard.js

用新的动物细节组件代替diet.join声明,并通过添加突出的行来通过饮食作为支持:

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import AnimalDetails from '../AnimalDetails/AnimalDetails';
 5
 6export default function AnimalCard({ diet, name, size }) {
 7  return(
 8    <div>
 9      <h3>{name}</h3>
10      <div>{size}kg</div>
11      <AnimalDetails
12        diet={diet}
13      />
14    </div>
15  )
16}
17
18AnimalCard.propTypes = {
19  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
20  name: PropTypes.string.isRequired,
21  size: PropTypes.number.isRequired,
22}

保存文件,你会看到新的细节在浏览器中。

Browser with details

通过一个组件传递细节与...props

各个部件配合良好,但动物卡中的效率略低。 你明确地从props ' 论点中剔除',但你没有使用数据。 相反,你正在把它传递到组件。 这从本质上来说没什么错——事实上,在太多的沟通方面犯错往往更好. 但是在这样做时,你使你的代码更难以维护. 每当想将新数据传递给 " 动物分类 " 时,都需要更新三个地方: " App " ,即通过道具的地方; " 动物分类 " ,即消耗道具的地方; " 动物分类 " ,即介于两者之间的地方.

更好的方法是收集AnimalCard内部未使用的奖励,然后将其直接传送到AnimalDetails。这会让你有机会对AnimalDetails进行更改,而不会更改AnimalCard

要做到这一点,您将使用 object rest operator。 该操作器收集在破坏过程中未被拉出来的任何项目,并将其保存到一个新的对象中。

这里有一个简单的例子:

1const dog = {
2    name: 'dog',
3    diet: ['meat']
4}
5
6const { name, ...props  } = dog;

在这种情况下,变量名称将是和变量props将是饮食:肉

到目前为止,你已经通过了所有副本,就像它们是HTML属性一样,但你也可以使用对象发送副本。

打开AnimalCard.js:

1nano src/components/AnimalCard/AnimalCard.js

内部,从被破坏的对象中移除饮食,然后将其余的补丁收集到一个叫做补丁的变量中,然后将这些补丁直接传递到动物细节:

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import AnimalDetails from '../AnimalDetails/AnimalDetails';
 5
 6export default function AnimalCard({ name, size, ...props }) {
 7  return(
 8    <div>
 9      <h3>{name}</h3>
10      <div>{size}kg</div>
11      <AnimalDetails
12        {...props}
13      />
14    </div>
15  )
16}
17
18AnimalCard.propTypes = {
19  name: PropTypes.string.isRequired,
20  size: PropTypes.number.isRequired,
21}

请注意,您可以删除饮食``PropType,因为您不使用此组件中的支撑。

在这种情况下,你只将一个标签传递到动物细节。在你有多个标签的情况下,该订单将具有重要性。后来的标签将重写以前的标签,所以如果你有一个标签,你想优先考虑,请确保它是最后一个。

保存并关闭文件. 浏览器将更新,一切将看起来相同:

Browser with details

要看到...props对象如何增加灵活性,让我们通过AnimalCard组件将scientificName传递到AnimalDetails

首先,打开App.js:

1nano src/components/App/App.js

然后将scientificName作为一个标签:

 1[label wrapper-tutorial/src/components/App/App.js]
 2import React from 'react';
 3import './App.css';
 4
 5import animals from './data';
 6import AnimalCard from '../AnimalCard/AnimalCard';
 7
 8function App() {
 9  return (
10    <div className="wrapper">
11      {animals.map(animal =>
12        <AnimalCard
13          diet={animal.diet}
14          key={animal.name}
15          name={animal.name}
16          size={animal.size}
17          scientificName={animal.scientificName}
18        />
19      )}
20    </div>
21  );
22}
23
24export default App;

保存并关闭文件。

跳过AnimalCard;您不需要在那里做出任何更改,然后打开AnimalDetails,以便您可以消耗新的补丁:

1nano src/components/AnimalDetails/AnimalDetails.js

新的接口将是一个字符串,您将添加到细节列表中,以及声明PropType的行:

 1[label wrapper-tutorial/src/components/AnimalDetails/AnimalDetails.js]
 2import React from 'react';
 3...
 4export default function AnimalDetails({ diet, scientificName }) {
 5  return(
 6    <div className="details">
 7      <h4>Details:</h4>
 8      <div>
 9        Scientific Name: {scientificName}.
10      </div>
11      <div>
12        Diet: {diet.map(food => convertFood(food)).join(' ')}
13      </div>
14    </div>
15  )
16}
17
18AnimalDetails.propTypes = {
19  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
20  scientificName: PropTypes.string.isRequired,
21}

当你这样做时,浏览器会更新,你会看到新的细节,没有任何改变的AnimalCard组件:

Browser with scientific name

在此步骤中,您学会了如何创建灵活的家长补贴,可以采取未知补贴并将其转移到嵌入式组件中,这是一个常见的模式,将为您提供创建具有专注责任的组件所需的灵活性。

步骤 3 — 使用孩子创建包装部件

在此步骤中,您将创建一个包装组件,可以将一组未知的组件作为支持,这将为您提供像标准HTML这样的组件的嵌套能力,并为您提供创建可重复使用的包装模式,这将允许您创建各种需要共同设计但灵活的内部组件。

React为您提供一个名为儿童的内置支架,可以收集任何儿童组件,从而使包装组件的创建更加直观和可读。

首先,创建一个名为卡片的新组件,这是一个包装组件,可为任何新卡片组件创建标准风格。

创建一个新目录:

1mkdir src/components/Card

然后在文本编辑器中打开卡片组件:

1nano src/components/Card/Card.js

创建一个组件,将孩子标题作为附件,并通过添加以下代码将其包裹到div中:

 1[label wrapper-tutorial/src/components/Card/Card.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import './Card.css';
 5
 6export default function Card({ children, title }) {
 7  return(
 8    <div className="card">
 9      <div className="card-details">
10        <h2>{title}</h2>
11      </div>
12      {children}
13    </div>
14  )
15}
16
17Card.propTypes = {
18  children: PropTypes.oneOfType([
19    PropTypes.arrayOf(PropTypes.element), 
20    PropTypes.element.isRequired
21  ]),
22  title: PropTypes.string.isRequired,
23}

对于孩子们来说,PropTypes是新的。孩子们可以是JSX元素,也可以是JSX元素的组合。

保存并关闭文件。

接下来,添加一些风格。打开Card.css:

1nano src/components/Card/Card.css

你的卡片将有一个边界和一个线条在细节下。

 1[label wrapper-tutorial/src/components/Card/Card.css]
 2.card {
 3    border: black solid 1px;
 4    margin: 10px;
 5    padding: 10px;
 6    width: 200px;
 7}
 8
 9.card-details {
10    border-bottom: gray solid 1px;
11    margin-bottom: 20px;
12}

现在你有你的组件,你需要使用它. 你可以包装每个动物卡组件在App.js,但因为名称动物卡意味着它已经是一个,最好使用动物卡内部的组件。

打开动物卡:

1nano src/components/AnimalCard/AnimalCard.js

与其他附件不同的是,您不会明确地传递孩子。相反,您将 JSX 列入,就像它们是 HTML 附件一样。

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import Card from '../Card/Card';
 5import AnimalDetails from '../AnimalDetails/AnimalDetails';
 6
 7export default function AnimalCard({ name, size, ...props }) {
 8  return(
 9    <Card title="Animal">
10      <h3>{name}</h3>
11      <div>{size}kg</div>
12      <AnimalDetails
13        {...props}
14      />
15    </Card>
16  )
17}
18
19AnimalCard.propTypes = {
20  name: PropTypes.string.isRequired,
21  size: PropTypes.number.isRequired,
22}

与 React 组件不同的是,你不需要一个根元素作为一个孩子,这就是为什么PropTypeCard指定它可以是一个组合的元素或一个元素。

保存和关闭文件. 当您这样做时,浏览器将更新,您将看到更新的卡片组件。

Browser with cards

现在,你有一个可重复使用的组件,可以带走任何数量的被窝儿童。 这样做的主要优点是,可以将用任意的部件再用。 如果要制作 " Plant " 牌,可以用 " Card " 部分包装植物信息。 它甚至不需要关联: 如果你想在列出音乐或账户数据等内容的完全不同的应用程序中重新使用卡片组件,你也可以这样做。 `卡'部分并不关心孩子是什么;你只是在重用包装器部分,在这种情况下,这就是有名的边框和标题.

使用孩子的缺点是,你只能有一个孩子支持的实例. 有时,你会想要一个组件在多个地方有自定义的JSX。

步骤4 — 将组件作为附件

在此步骤中,您将更改您的卡片组件以将其他组件作为附件。这将为您的组件提供最大的灵活性,以在页面上显示未知的组件或 JSX 在多个位置。

到此步骤结束时,您将有一个组件,可以包装子组件,并在卡片中显示其他组件. 此模式将为您提供灵活性,当您需要创建需要比简单字符串和整数更复杂的信息的组件时。

让我们修改卡片组件,以选择一个名为细节的任意 React 元素。

首先,打开卡片组件:

1nano src/components/Card/Card.js

接下来,添加一个名为细节的新支撑,并将其放置在<h2>元素下面:

 1[label wrapper-tutorial/src/components/Card/Card.js]
 2import React from 'react';
 3import PropTypes from 'prop-types';
 4import './Card.css';
 5
 6export default function Card({ children, details, title }) {
 7  return(
 8    <div className="card">
 9      <div className="card-details">
10        <h2>{title}</h2>
11        {details}
12      </div>
13      {children}
14    </div>
15  )
16}
17
18Card.propTypes = {
19  children: PropTypes.oneOfType([
20    PropTypes.arrayOf(PropTypes.element), 
21    PropTypes.element.isRequired
22  ]),
23  details: PropTypes.element,
24  title: PropTypes.string.isRequired,
25}
26
27Card.defaultProps = {
28  details: null,
29}

此插件的类型与儿童相同,但应该是可选的。 为了使其可选,您添加了null的默认值。 在这种情况下,如果用户没有传输任何细节,该组件仍然有效,不会显示任何额外的内容。

保存并关闭文件. 页面将更新,您将看到与以前相同的图像:

Browser with cards

现在在动物卡中添加一些细节,首先打开动物卡

1nano src/components/AnimalCard/AnimalCard.js

由于卡片组件已经使用孩子,您将需要通过新的JSX组件作为支持,因为这些都是哺乳动物,请将其添加到卡片中,但将其包裹在<em>标签中,以使其意大利式。

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3...
 4
 5export default function AnimalCard({ name, size, ...props }) {
 6  return(
 7    <Card title="Animal" details={<em>Mammal</em>}>
 8      <h3>{name}</h3>
 9      <div>{size}kg</div>
10      <AnimalDetails
11        {...props}
12      />
13    </Card>
14  )
15}
16...

当你这样做时,浏览器会更新,你会看到更新,包括短语 Mammal

Browser with card and details

这个支撑已经强大,因为它可以采取任何尺寸的JSX。在这个例子中,你只添加了一个元素,但你可以通过尽可能多的JSX,因为它不必是JSX。如果你有一个复杂的标记,例如,你不希望直接在支撑中传递它;这将是很难读取的。

要在工作中看到这一点,请将动物细节转到细节中:

 1[label wrapper-tutorial/src/components/AnimalCard/AnimalCard.js]
 2import React from 'react';
 3...
 4
 5export default function AnimalCard({ name, size, ...props }) {
 6  return(
 7    <Card
 8      title="Animal"
 9      details={
10        <AnimalDetails
11          {...props}
12        />
13      }
14    >
15      <h3>{name}</h3>
16      <div>{size}kg</div>
17    </Card>
18  )
19}
20...

动物细节更复杂,有几个标记行,如果你将其直接添加到细节,它将大大增加标记,并使其难以读取。

保存和关闭文件. 当您这样做时,浏览器将更新,详细信息将出现在卡片的顶部。

Card with details at the top

现在你有一个卡片组件,可以使用自定义的JSX并将其放置在多个位置. 你不受限制于一个单一的附件;你可以将元素传递到你想要的许多附件。

通过一个组件作为一个支撑不是完美的。它更难读,不像通过孩子那么清晰,但它们同样灵活,你可以在一个组件中使用你想要的尽可能多的组件。

在此步骤中,您学会了如何将 JSX 和 React 组件作为附件传递给另一个组件,这将为您的组件提供灵活性,以处理许多包装组件可能需要多个附件来处理 JSX 或组件的情况。

结论

您创建了各种可以灵活显示数据的包接组件,同时保持可预测的外观和结构. 您创建了可以收集和传递未知道具到嵌入组件的组件. 您还使用内置的 " 儿童 " 道具来创建可以处理任意数量的嵌入元素的包装组件。 最后,您创建了一个可以将JSX或React组件作为道具的组件,这样您的包装组件就可以处理多个不同定制的例.

Wrapper 组件为您提供了适应未知情况的能力,同时最大限度地提高代码的重复使用和一致性. 这种模式有助于创建您将在应用程序中重复使用的基本 UI 元素,包括:按钮,警告,模式,幻灯片显示等。

如果您想查看更多 React 教程,请查看我们的 React 主题页面,或返回 如何在 React.js 系列中编码页面

Published At
Categories with 技术
comments powered by Disqus