Автор выбрал Creative Commons для получения пожертвования в рамках программы Write for DOnations.
В этом обучающем модуле мы научимся создавать пользовательские компоненты в React. Компоненты — это независимые функциональные элементы, которые можно многократно использовать в приложениях. Все приложения React строятся на основе компонентов. Это могут быть простые функции и классы JavaScript, но их можно использовать как персонализированные элементы HTML. Кнопки, меню и любые другим материалы на главной странице пользовательского интерфейса можно создавать как компоненты. Компоненты также могут содержать информацию о состоянии и разметку экрана.
Когда вы научитесь создавать компоненты в React, вы сможете разбивать сложные приложения на более удобные в сборке и обслуживании составные части.
В этом обучающем модуле мы создадим список эмодзи, при нажатии на которые будут выводиться их имена. Эмодзи будут создаваться с помощью пользовательского компонента и вызываться из другого пользовательского компонента. К завершению этого обучающего модуля вы научитесь создавать пользовательские компоненты с использованием классов и функций JavaScript и поймете, как разделять существующий код на компоненты для многоразового использования и сохранять компоненты в удобной для чтения файловой структуре.
Вам потребуется среда разработки для 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.
Мы используем синтаксис JSX, о котором можно более подробно узнать в обучающем модуле «Создание элементов с помощью JSX».
Также вам потребуются базовые знания JavaScript, которые вы можете получить в руководстве Написание кода на JavaScript, а также базовые знания HTML и CSS. Хорошим источником информации о HTML и CSS является сеть разработчиков Mozilla.
На этом шаге мы создадим основу для проекта, используя приложение Create React. Также мы изменим проект по умолчанию и создадим базовый проект со списком эмодзи и некоторыми изменениями стиля.
Прежде всего, создайте новый проект. Откройте терминал и запустите в нем следующую команду:
После этого переключитесь в каталог проекта:
Откройте код App.js
в текстовом редакторе:
Затем возьмите шаблонный код, созданный приложением Create React и замените его содержание новым кодом React, который выводит список эмодзи:
В этом коде используется синтаксис JSX для использования функции map()
в массиве emojis
и вывода списка эмодзи как элементов списка <li>
. Также данный код прикрепляет события onClick
для отображения данных об эмодзи в браузере. Чтобы изучить код более подробно, ознакомьтесь с документом Создание элементов React с помощью JSX, содержащим подробное разъяснение JSX.
Сохраните и закройте файл. Теперь вы можете удалить файл logo.svg
, поскольку он являлся частью шаблона, и мы больше не ссылаемся на него:
Далее мы изменим стили. Откройте файл src/App.css
:
Замените его содержимое следующим кодом CSS, чтобы выровнять элементы по центру и изменить шрифт:
Здесь используется flex
для выравнивания по центру главных элементов <h1>
и элементов списка. Также здесь удалены стили кнопок по умолчанию и стили <li>
, и поэтому эмодзи будут отображаться в одной строке. Более подробную информацию можно найти в документе Создание элементов React с помощью JSX.
Сохраните и закройте файл.
Откройте другое окно терминала в корневом каталоге проекта. Запустите проект с помощью следующей команды:
После запуска команды вы увидите проект в браузере по адресу http://localhost:3000
.
Оставляйте этот экран работать, пока вы работаете над проектом При каждом сохранении проекта браузер автоматически обновляется и показывает актуальный код.
Вы увидите страницу проекта с надписью Hello, World и тремя эмодзи, указанными вами в файле App.js
:
Мы настроили код и теперь можем начать сборку компонентов в React.
Мы запустили проект и теперь можем начать создание собственных компонентов. На этом шаге мы создадим независимый компонент React, расширив базовый класс React Component
. Вы создадите новый класс, добавите для него метода и используете функцию render для вывода данных.
Компоненты React — это самодостаточные элементы, которые можно использовать на странице любое количество раз. Создавая небольшие фрагменты кода для определенных задач, вы можете использовать их в разных частях приложения по мере его роста. Очень важно, что это самодостаточные элементы узкого назначения, и их можно использовать для разделения кода на логические структурные составляющие. Фактически мы уже поработали с логически разделенными компонентами. Файл App.js
представляет собой функциональный компонент, о чем вы подробнее узнаете на шаге 3.
Всего существует два типа пользовательских компонентов: основанные на классах и основанные на функциях. Вначале мы создадим компонент на базе класса. Вы создадите новый компонент Instructions
, разъясняющий инструкции для средства просмотра эмодзи.
Примечание. Компоненты на базе класса раньше были наиболее популярным способом создания компонентов React. Однако с появлением React Hooks многие разработчики и библиотеки переходят на использование функциональных компонентов.
Хотя функциональные компоненты стали нормой, компоненты класса часто можно встретить в старом коде. Они вам не потребуются, но вам нужно будет уметь распознавать их. Также они помогут хорошо познакомиться с многими будущими концепциями, такими как управление состоянием. В этом обучающем модуле мы научимся создавать компоненты класса и функциональные компоненты.
Вначале создайте новый файл. Имена файлов компонентов принято начинать с заглавной буквы:
Затем откройте в файл в своем текстовом редакторе:
Вначале импортируйте компоненты React
и класс Component
и экспортируйте Instructions
:
При импорте React
выполнит конвертацию JSX. Component
— это базовый класс, который вы расширяете для создания вашего компонента. Вы создали класс с именем вашего компонента (Instructions
) и расширили базовый класс Component
строкой export
. Также вы экспортируете этот класс как класс по умолчанию, используя ключевые слова export default
в начале декларации класса.
Название класса должно начинаться с заглавной буквы и должно соответствовать имени файла. Это важно при использовании инструментов отладки, отображающих название компонента. Если название соответствует файловой структуре, вам будет легче найти нужный компонент.
В базовом классе Component
имеется несколько методов, которые вы можете использовать в своем собственном классе. Наиболее важный из них — метод render()
, который мы будем использовать в этом обучающем модуле. Метод render()
возвращает код JSX, который нужно отобразить в браузере.
Для начала добавим небольшое описание приложения в теге <p>
:
Сохраните и закройте файл. Пока в браузере не произошло никаких изменений. Это связано с тем, что мы еще не использовали новый компонент. Чтобы использовать компонент, нужно добавить его в другой компонент, связанный с корневым компонентом. В этом проекте <App>
является корневым компонентом index.js
. Чтобы он отображался в приложении, вам нужно добавить кое-что в компонент <App>
.
Откройте src/App.js
в текстовом редакторе:
Вначале вам нужно будет импортировать компонент:
Поскольку это импорт по умолчанию, вы можете использовать любое желаемое имя. Для удобства чтения лучше всего обеспечить единство имен. Импорт должен соответствовать названию компонента, которое должно соответствовать имени файла. Единственное твердое правило заключается в том, что название компонента должно начинаться с заглавной буквы. Именно так React понимает, что это компонент React.
Вы импортировали компонент, и теперь его нужно добавить в код, как если бы это был пользовательский элемент HTML:
В этом коде мы заключили компонент в угловые скобки. Поскольку у этого компонента нет дочерних элементов, он может закрываться самостоятельно с окончанием />
.
Сохраните файл. Когда вы закроете его, страница обновится, и вы увидите новый компонент.
Текст у нас есть, и теперь можно добавить изображение. Загрузите изображение эмодзи с сайта wikimedia и сохраните его в каталоге src
под именем emoji.svg
с помощью следующей команды:
curl
отправляет запрос URL, а флаг -o
позволяет сохранить файл как src/emoji.svg
.
Откройте файл компонента:
Импортируйте эмодзи и добавьте его в свой компонент с помощью динамической ссылки:
Обратите внимание, что при импорте нужно указать расширение файла .svg
. Во время импорта мы импортируем динамический путь, созданный webpack при компиляции кода. Дополнительную информацию можно найти в документе «Настройка проекта React с помощью приложения Create React».
Вам потребуется закрыть теги <img>
и <p>
пустыми тегами, чтобы выводился только один элемент.
Сохраните файл. При перезагрузке изображение будет очень большим по сравнению с остальным контентом:
Чтобы уменьшить изображение, нужно будет добавить код CSS и className
в пользовательский компонент.
Вначале замените в файле Instructions.js
пустые теги на div и присвойте параметру className
значение instructions
:
Сохраните и закройте файл. Откройте файл App.css
:
Создайте правила выбора
класса для instructions class selector:
При добавлении отображения
стилей flex
вы выравниваете img
и p
по центру с помощью flexbox. Вы изменили направление так, что все содержимое экрана выравнивается по вертикали, с помощью flex-direction: column;
. Строка align-items: center;
выравнивает элементы по центру экрана.
Теперь элементы выровнены, и вам нужно изменить размер изображения. Задайте для img
внутри div
значения width
и height
в 100px
.
Сохраните и закройте файл. Браузер перезагрузится, и вы увидите уменьшенное изображение:
Вы создали независимый пользовательский компонент, который можно использовать много раз. Чтобы посмотреть возможности многократного использования, добавьте второй экземпляр в App.js
.
Откройте App.js
:
Добавьте в App.js
второй экземпляр компонента:
Сохраните файл. Когда браузер перезагрузится, вы увидите компонент два раза.
В данном случае нам не нужны два экземпляра компонента Instructions
, но вы видите, что компонент можно эффективно использовать несколько раз. При создании специальных кнопок или таблиц вы можете использовать их на одной странице несколько раз, и для их реализации идеально подойдут пользовательские компоненты.
Пока что удалите лишний тег image. Удалите в текстовом редакторе второй компонент <Instructions />
и сохраните файл:
Теперь у вас имеется самодостаточный компонент, который вы можете несколько раз добавить в родительский компонент. Данная структура хорошо работает при небольшом количестве компонентов, но есть небольшая проблема. Все файлы перемешаны друг с другом. Изображение для <Instructions>
находится в том же каталоге, что и ресурсы для <App>
. Также вы сочетаете код CSS для <App>
с кодом CSS для <Instructions>
.
На следующем шаге мы создадим файловую структуру, которая сделает каждый компонент независимым посредством группирования их функций, стилей и зависимостей. Это даст вам возможность перемещать компоненты по мере необходимости.
На этом шаге мы создадим файловую структуру для организации компонентов и их ресурсов, таких как изображения, таблицы CSS и другие файлы JavaScript. Мы будем группировать код по компонентам, а не по типу ресурсов. Это означает, что у нас не будет отдельных каталогов для файлов CSS, изображений и JavaScript. Вместо этого у нас будет отдельный каталог для каждого компонента, и в этом каталоге будут содержаться соответствующие элементы CSS, JavaScript и изображения. В обоих случаях мы разделяем сложности.
Поскольку у нас имеется независимый компонент, нам нужна файловая структура для группировки соответствующего кода. Сейчас все хранится в одном каталоге. Выведите все элементы из каталога src
:
На экране вы увидите, что все довольно запутанно:
OutputApp.css Instructions.js index.js
App.js emoji.svg serviceWorker.js
App.test.js index.css setupTests.js
Код компонента <App>
(App.css
, App.js
и App.test.js
) хранится вместе с кодом корневого компонента (index.css
и index.js
) и кодом вашего компонента Instructions.js
.
React намеренно игнорирует структуру файлов. Он не рекомендует какую-то определенную структуру, и проект может использовать самые разнообразные иерархии файлов. Однако мы рекомендуем немного упорядочить его, чтобы избежать перегрузки корневого каталога компонентами, файлами CSS и изображениями, в которых будет трудно сориентироваться. Кроме того, явное присвоение имен упрощает определение связанных частей проекта. Например, файл изображения Logo.svg
вряд ли может быть частью компонента Header.js
.
Одна из самых простых структур предполагает создание каталога components
, содержащего отдельные каталоги для каждого компонента. Это позволит группировать компоненты отдельно от кода конфигурации (например, serviceWorker
) и при этом группировать ресурсы с компонентами.
Components
Для начала создайте каталог с именем components
:
Затем переместите в каталог следующие компоненты и код: App.css
, App.js
, App.test.js
, Instructions.js
и emoji.svg
:
Здесь мы используем подстановочный символ (*
), чтобы выбрать все файлы, начинающиеся с App.
.
После перемещения кода вы увидите ошибку на терминале, где выполняется npm start
.
OutputFailed to compile.
./src/App.js
Error: ENOENT: no such file or directory, open 'your_file_path/tutorial-03-component/src/App.js'
Помните, что импорт кода выполняется с использованием относительных путей. Если вы измените путь для некоторых файлов, вам нужно будет обновить код.
Для этого откройте файл index.js
.
Измените путь импорта App
для импорта из каталога components/
.
Сохраните и закройте файл. Скрипт обнаружит изменения, и сообщение об ошибке исчезнет.
Теперь компоненты хранятся в отдельном каталоге. По мере усложнения ваших приложений вы можете начать использовать каталоги для служб API, хранилищ данных и утилитарных функций. Отделение кода компонентов будет первым шагом, однако код CSS для компонента Instructions
все еще находится в файле App.css
. Для логического разделения нужно предварительно переместить компоненты в отдельные каталоги.
Вначале нужно создать специальный каталог для компонента <App>
:
Затем нужно переместить сопутствующие файлы в новый каталог:
Вы получите похожее сообщение об ошибке в последнем разделе:
OutputFailed to compile.
./src/components/App.js
Error: ENOENT: no such file or directory, open 'your_file_path/tutorial-03-component/src/components/App.js'
В этом случае вам нужно будет обновить две вещи. Вначале нужно будет обновить путь в файле index.js
.
Откройте файл index.js
:
Обновите путь импорта App, чтобы он указывал на компонент App
в каталоге App
.
Сохраните и закройте файл. Приложение все еще не будет работать. Вы увидите следующее сообщение об ошибке:
OutputFailed to compile.
./src/components/App/App.js
Module not found: Can't resolve './Instructions.js' in 'your_file_path/tutorial-03-component/src/components/App'
Поскольку компонент <Instructions>
находится не в том же каталоге, что и компонент <App>
, вам нужно будет изменить путь импорта. Перед этим создайте каталог для компонента Instructions
. Создайте каталог Instructions
внутри каталога src/components
:
Затем переместите в этот каталог файлы Instructions.js
и emoji.svg
:
Мы создали компонент Instructions
и теперь можем завершить обновление путей файлов для подключения компонента к приложению.
импорта
Теперь компоненты находятся в отдельных каталогах, и мы можем изменить путь импорта в App.js
.
Откройте App.js
:
Поскольку путь является относительным, вам нужно будет перейти на один уровень вверх в каталог src/components
, а затем перейти в каталог Instructions
для получения файла Instructions.js
. Поскольку это не файл JavaScript, вам не потребуется заключительный импорт.
Сохраните и закройте файл. Теперь вы используете правильные пути для импорта, и ваш браузер обновит экран и выведет приложение.
Примечание. Вы также можете вызывать корневой файл в каждом каталоге index.js
. Например, вместо src/components/App/App.js
вы можете создать файл src/components/App/index.js
. Это позволит немного уменьшить строку импорта. Если путь указывает на каталог, при импорте приложение будет искать файл index.js
. Для импорта src/components/App/index.js
в файл src/index.js
нужно использовать команду import ./components/App
. Недостатком этого подхода заключается большое количество файлов с одним именем, что может создать сложности в некоторых текстовых редакторах. Это личное решение и решение команды, но лучше всего действовать согласованно.
Теперь у каждого компонента имеется собственный каталог, но компоненты еще не полностью независимы. Последний шаг заключается в том, чтобы извлечь код CSS для компонента Instructions
в отдельный файл.
Для начала создайте файл CSS в каталоге src/components/Instructions
:
Затем откройте файл CSS в текстовом редакторе:
Добавьте код CSS для инструкций, созданный на предыдущем шаге:
Сохраните и закройте файл. Затем удалите код CSS для инструкций из файла src/components/App/App.css
.
Удалите строки, где упоминается .instructions
. Итоговый файл будет выглядеть следующим образом:
Сохраните и закройте файл. В заключение импортируйте код CSS в файл Instructions.js
:
Импорт CSS с использованием относительного пути:
Сохраните и закройте файл. Окно браузера будет выглядеть так же, как и раньше, но теперь все файловые ресурсы будут сгруппированы в одном каталоге.
Еще раз посмотрим на структуру. Вначале идет каталог src/
:
У нас имеется корневой компонент index.js
и связанный файл CSS index.css
рядом с каталогом components/
и служебными файлами serviceWorker.js
, setupTests.js
и т. д.:
Outputcomponents serviceWorker.js
index.css setupTests.js
index.js
Теперь войдем в каталог components
:
Вы увидите в нем отдельный каталог для каждого компонента:
OutputApp Instructions
Если вы посмотрите в каждый из этих каталогов, вы найдете там код компонента, код CSS, тестовые файлы и файлы изображений, если они есть.
OutputApp.css App.js App.test.js
OutputInstructions.css Instructions.js emoji.svg
Итак, мы создали надежную структуру проекта. Мы переместили довольно много кода, но со структурой масштабирование станет намного проще.
Это не единственный способ построения структуры. В некоторых файловых структурах используется концепция разделения кода посредством указания каталога, разбиваемого на разные пакеты. Другие файловые структуры разделяются по маршруту и используют общий каталог для компонентов, которые используются на разных маршрутах.
Пока что нужно применять менее сложный подход. Если появится необходимость в другой структуре, легче будет перейти от простого к сложному. Если начать со сложной структуры, перестроиться впоследствии будет сложно.
Мы создали и организовали компонент на базе класса. На следующем шаге мы создадим функциональный компонент.
На этом шаге мы создадим функциональный компонент. В современном коде React чаще всего используются функциональные компоненты. Эти компоненты более короткие, чем компоненты на базе классов, и в отличие от них могут использовать хуки React. Хуки — это нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.
Функциональный компонент — это функция JavaScript, возвращающая JSX. Функция не требует расширения и не нужно запоминать никаких специальных методов.
Чтобы превратить <Instructions>
в функциональный компонент нужно изменить класс на функцию и удалить метод render, чтобы осталось только одно выражение return.
Для этого вначале откройте Instructions.js
в текстовом редакторе.
Замените декларацию class
декларацией function
:
Удалите импорт { Component }
:
Удалите метод render()
. Теперь вы возвращаете только код 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!