Автор выбрал Creative Commons для получения пожертвования в рамках программы Write for DOnations.
В этом обучающем модуле вы создадите компоненты обертки со свойствами с помощью библиотеки JavaScript React. Компоненты обертки — это компоненты, которые окружают неизвестные компоненты и предоставляют структуру по умолчанию для отображения дочерних компонентов. Эта схема полезна для создания элементов пользовательского интерфейса (UI), неоднократно используемых по всей конструкции, например типичных схем, шаблонов страниц и информационных плиток.
Для создания компонентов обертки сначала следует научиться использовать операторы rest и spread для сбора неиспользуемых свойств для передачи вложенным компонентам. Затем вы создадите компонент, который использует встроенный компонент children
для обертки вложенных компонентов в JSX, как если бы они были элементами HTML. Наконец, вы передадите компоненты как свойства для создания гибких оберток, которые могут встроить настраиваемый JSX в разные места в компоненте.
В этом обучающем модуле вы создадите компоненты для отображения списка данных о животных в форме карточек. Вы научитесь разделять данные и компоненты реорганизации кода по мере создания гибких компонентов обертки. К концу этого обучающего модуля мы получим рабочее приложение, которое будет использовать расширенные методы свойств для создания многоразовых компонентов, которые будут масштабироваться и адаптироваться по мере развития и изменения приложения.
Примечание. В качестве первого шага необходимо настроить пустой проект, на основе которого вы будете выполнять упражнение из руководства. Если у вас уже есть рабочий проект и вы хотите напрямую работать со свойствами, начните выполнение руководства с шага 2.
Вам потребуется среда разработки для Node.js. Данный обучающий модуль был протестирован с версией Node.js 10.20.1 и версией npm 6.14.4. Чтобы установить его в macOS или Ubuntu 18.04, следуйте указаниям руководства Установка Node.js и создание локальной среды разработки в macOS или раздела Установка с помощью PPA руководства Установка Node.js в Ubuntu 18.04.
В этом обучающем модуле вы создадите приложение с помощью приложения Create React App. Вы можете найти инструкции для установки приложения с помощью Create React App и общую информацию о том, как оно работает, в статье Создание и настройка проекта React с помощью приложения Create React App.
Вы будете использовать компоненты React, о которых вы можете узнать из нашего обучающего модуля Создание пользовательских компонентов в React. Это также позволит получить базовое понимание свойств React, о которых вы можете узнать из модуля Настройка компонентов React с помощью свойств.
Также вам потребуются базовые знания JavaScript, которые вы можете получить в серии руководств Написание кода на JavaScript, а также базовые знания HTML и CSS. Хорошим источником информации о HTML и CSS является сеть разработчиков Mozilla.
На этом шаге мы создадим новый проект, используя Create React App. Затем вы удалите пример проекта и связанные файлы, которые устанавливаются при инициализации проекта. В заключение вы создадите простую структуру файлов для организации ваших компонентов. Это позволит получить надежную основу для создания приложения обертки этого обучающего руководства в следующем шаге.
Создайте новый проект. В командной строке запустите следующий скрипт для установки нового проекта с помощью create-react-app
:
- npx create-react-app wrapper-tutorial
После завершения создания проекта перейдите в его директорию:
- cd wrapper-tutorial
В новой вкладке или окне терминала запустите проект, используя скрипт start Create React App. Браузер автоматически обновит изменения, поэтому оставьте запущенным этот скрипт, пока вы работаете:
- npm start
Вы получите запущенный локальный сервер. Если проект не был открыт в браузере, вы можете открыть его, перейдя на страницу http://localhost:3000/
. Если вы запустили приложение на удаленном сервере, воспользуйтесь адресом http://your_IP_address:3000
.
Ваш браузер загрузит простое приложение React в качестве элемента Create React App:
Вы должны будете создать абсолютно новый набор компонентов, поэтому вам нужно начать с удаления определенного шаблонного кода, чтобы получить пустой проект.
Откройте src/App.js
в текстовом редакторе. Это корневой компонент, который встраивается в страницу. Все компоненты будут запускаться отсюда. Дополнительную информацию об App.js
можно найти в статье Настройка проекта React с помощью Create React App.
Откройте 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
Оператор импорта должен указывать на файл 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();
Сохраните и закройте файл.
Теперь, когда проект настроен, вы можете создать ваш первый компонент.
...props
На этом шаге вы создадите компонент для отображения набора данных о группе животных. Ваш компонент будет содержать второй вложенный компонент для отображения определенной информации. Для подключения родительского и вложенного компонентов вы будете использовать операторы rest и spread для передачи неиспользуемых свойств от родительского компонента вложенному без необходимости знания родительским компонентом имен или типов свойств.
К концу этого шага у вас будет родительский компонент, который может предоставлять свойства вложенным компонентам без необходимости знать, что это за свойства. Это сохранит гибкость родительского компонента и позволит обновлять дочерний компонент без необходимости изменять родительский.
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
, которое React будет использовать для отслеживания сопоставленных данных. Наконец, вы обернете код с помощью div
в className
wrapper
, который вы будете использовать для добавления определенного оформления.
Для добавления этого оформления откройте App.css
:
- nano src/components/App/App.css
Удалите шаблонное оформление и добавьте гибкие свойства в класс, называемый 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
для применения правила к элементам с className
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
не требуется ничего знать о свойствах или PropTypes
, которые идут в AnimalDetails
.
Для этого вы будете использовать оператор rest объекта. Этот оператор собирает все элементы, которые не были извлечены во время деструктурирования и сохраняет их в новый объект.
Вот простой пример:
const dog = {
name: 'dog',
diet: ['meat']
}
const { name, ...props } = dog;
В этом случае переменная name
будет 'dog'
, а переменная props
будет { diet: ['meat']}
.
До сих пор вы передавали все свойства, как если бы они были свойствами HTML, но вы также можете использовать объекты для отправки свойств. Чтобы использовать объект в качестве свойства, необходимо использовать оператор spread — ...props
— в фигурных скобках. Это изменит каждую пару ключ-значение на свойство.
Откройте 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,
}
Обратите внимание, что вы можете удалить PropType
diet
, поскольку вы не используете свойство в этом компоненте.
В этом случае вы только передаете одно свойство 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
Новое свойство будет строкой, которую вы добавите в список 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
:
На этом шаге вы научились создавать гибкие родительские свойства, которые могут принимать неизвестные свойства передавать их во вложенные компоненты с помощью оператора spread. Это обычная схема, обеспечивающая гибкость создания компонентов с определенными обязанностями. В следующем шаге вы создадите компоненты, которые могут принимать неизвестные компоненты в качестве свойства с помощью встроенного свойства children
.
children
На этом шаге вы создадите компонент обертки, который может принимать неизвестную группу компонентов в качестве свойства. Это позволит вам вкладывать такие компоненты, как стандартный HTML, и даст схему для создания многоразовых оберток, позволяющих создавать множество компонентов, которым нужен общий дизайн, но при этом гибкая внутренняя часть.
React дает встроенное свойство под названием children
, которое собирает все дочерние компоненты. Это позволяет создавать интуитивные и читаемые компоненты обертки.
Для начала создайте новый компонент под названием Card
. Это будет компонент обертки для создания стандартного стиля оформления для всех новых компонентов карточки.
Создайте новый каталог:
- mkdir src/components/Card
Затем откройте компонент Card
в своем текстовом редакторе:
- nano src/components/Card/Card.js
Создайте компонент, который принимает children
и title
в качестве свойства и оборачивает их в 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
В отличие от других свойств вы не передаете 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
, указанный для Card
, может быть массивом элементов или одиночным элементом. Помимо передачи children
как вложенных компонентов, вы даете карточке заголовок Animal
.
Сохраните и закройте файл. Когда вы закроете его, браузер обновится, и вы увидите обновленный компонент карточки.
Теперь у вас есть многоразовый компонент Card
, который может принимать любое количество вложенных дочерних свойств. Основное преимущество этого заключается в том, что вы можете повторно использовать Card
с любым произвольным компонентом. Если вы хотите сделать карту Plant
, это можно сделать, обернув информацию о растении в компонент Card
. Даже не требуется никаких соотношений: если вы хотите повторно использовать компонент Card
в совершенно других приложениях, где указываются, например, музыкальные данные или данные учетной записи, это также возможно. Компоненту Card
неважны дочерние компоненты, вы просто повторно используете элемент обертки, который в данном случае является границей и заголовком, выполненным в определенном стиле.
Минусом использования children
является то, что вы сможете иметь только один экземпляр дочернего свойства. В отдельных случаях вам понадобится, чтобы компонент имел настраиваемый JSX в разных местах. К счастью, вы можете это сделать, передав компоненты JSX и React как свойства, которые мы рассмотрим в следующем шаге.
На этом шаге вы измените компонент Card
для получения других компонентов как свойств. Это придаст вашему компоненту максимальную гибкость для отображения неизвестных компонентов или JSX в разных местах на странице. В отличие от children
, который можно использовать только один раз, вы можете иметь столько компонентов, сколько есть свойств, обеспечивая для вашего компонента обертки способность адаптироваться к различным потребностям и в то же время поддерживать стандартный вид и структуру.
К концу этого шага у вас будет компонент, который сможет обернуть дочерние компоненты, а также отобразить другие компоненты в карточке. Эта структура обеспечит гибкость при создании компонентов, которым нужна информация сложнее, чем простые строки и целые числа.
Теперь изменим компонент 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 как свойство. Поскольку все эти животные являются млекопитающими, добавьте это в карточку, но оберните в теги <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 (млекопитающее).
Это свойство уже является мощным, поскольку оно может принимать JSX любого размера. В этом примере вы добавили только один элемент, но вы можете передать столько JSX, сколько хотите. Это также необязательно должен быть JSX. Если бы у вас была сложная метка, например, вы бы не хотели передавать ее напрямую в свойстве, это бы читалось бы с трудом. Вместо этого вы можете создать отдельный компонент и затем передать компонент как свойство.
Чтобы увидеть это в действии, передайте 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 и размещать его в разных точках. Вы не ограничены одним свойством, вы можете передавать элементы желаемому количеству свойств. Это дает вам возможность создавать гибкие компоненты обертки, которые могут предоставлять другим разработчикам возможность настраивать компонент, сохраняя общий стиль и функциональность.
Передача компонента как свойства не является идеальной. Они немного труднее читаются и не настолько понятны, как при передаче children
, но они являются гибкими, и вы можете использовать их в компоненте в любом количестве. Сначала следует использовать children
, но если этого недостаточно, смело возвращайтесь к свойствам.
На этом шаге вы научились передавать компоненты JSX и React как свойства другому компоненту. Это обеспечит гибкость вашего компонента для поведения в различных ситуациях, где компоненту обертки могут потребоваться различные свойства для обращения с JSX или компонентами.
Вы создали различные компоненты обертки, которые могут гибко отображать данные и в то же время поддерживать прогнозируемый вид и структуру. Вы создали компоненты, которые могут собирать и передавать неизвестные свойства во вложенные компоненты. Также вы использовали встроенное свойство children
для создания компонентов обертки, которое может обрабатывать произвольное количество вложенных элементов. Наконец, вы создали компонент, который может принимать компоненты JSX или React как свойство для того, чтобы ваш компонент обертки мог обрабатывать различные экземпляры разных конфигураций.
Компоненты обертки позволяют адаптироваться к неизвестным обстоятельствам, а также максимально увеличивают возможность повторного использования кода и обеспечивают его согласованность. Эта структура полезна для создания базовых элементов пользовательского интерфейса, которые вы будете использовать повторно по всему приложению, включая кнопки, предупреждения, типичные схемы, слайд-шоу и многое другое. Вы вернетесь к нему еще неоднократно.
Если вас интересуют другие обучающие модули по React, ознакомьтесь с нашей страницей тем по React или вернитесь на страницу серии Программирование на React.js.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!