- Оригинальный адрес:structuring projects and naming components in react
- Оригинальный автор:Vinicius Dacal
- Перевод с:Команда облачных переводчиков Alibaba
- Ссылка на перевод:GitHub.com/рассветные команды/…
- Переводчик:также дерево
Структура проекта React и наименование компонентов
Реагируйте как библиотека, не определяет, как вы организуете структуру проекта. Это хорошая вещь, потому что у нас есть полная свобода, чтобы попробовать разные организационные методы и выбрать способ, которым лучше всего подходит нам. Но с другой точки зрения, это может заставить разработчиков, которые только что начали реагировать на некоторое запутанное.
В этой статье я покажу вам методы, которые я использовал в течение некоторого времени и которые хорошо себя зарекомендовали, не изобретая велосипед, а комбинируя и совершенствуя решения сообщества.
Примечание: здесь нет ничего абсолютно правильного! Вы можете выбрать то, что, по вашему мнению, легко понять и может быть адаптировано или адаптировано к вашей ситуации.
Структура каталогов
Один из самых частых вопросов, которые я получаю, — как организовать файлы и структуры каталогов. В этой статье мы предполагаем, что у вас естьcreate-react-app
Сгенерирована простейшая структура каталогов.
create-react-app
Создал базовый проект для нас, включая корневой каталог и например.gitignore
, package.json
, README.md
, yarn.lock
документ.
это также сгенерировалоpublic
а такжеsrc
содержание,src
Каталог — это каталог, в котором мы храним наш исходный код.
Взгляните на структуру, изображенную на изображении ниже:
В этой статье мы остановимся только наsrc
каталог, все за его пределами останется неизменным.
Контейнеры и компоненты
мы можем видеть вsrc
В каталоге есть каталог контейнеров и каталог компонентов:
src
├─ components
└─ containers
Но такой подход приводит к следующим проблемам:
- субъективные правилаВы не знаете, что такое контейнер и что такое компонент, разница между ними определяется субъективно. Заставить всех разработчиков одобрять и оценивать одинаково очень сложно, если это реализовано в вашей команде.
-
Изменения в компонентах не учитываютсяДаже если вы решите, что компонент подходит для определенного вида, он может легко измениться в течение жизни проекта, что в итоге вынудит вас переместить его из
components
перейти кcontainers
каталог и наоборот. - Разрешить двум компонентам использовать одно и то же имяКомпоненты должны быть названы декларативно и уникально в приложении, чтобы избежать путаницы в отношении обязанностей компонентов с одинаковыми именами. Но описанный выше подход открывает пробел, когда два компонента могут иметь одно и то же имя, один может быть контейнером, а другой может быть презентационным компонентом.
- низкая эффективностьДаже когда вы реализуете автономную функцию, вам приходится много переключаться между каталогами контейнеров и компонентов, потому что для автономной функции нормально иметь два разных типа компонентов.
Существует вариант, основанный на этом подходе, в котором два каталога хранятся отдельно в каталоге модуля.
Представьте, что у вас есть пользовательский модуль в вашем приложении, и в этом модуле у вас есть два каталога для разделения ваших компонентов:
src
└─ User
├─ components
└─ containers
Описанный выше подход сводит к минимуму проблему постоянного переключения между двумя удаленными каталогами, но и добавляет немало хлопот. Когда в вашем приложении много модулей, вы можете создать десятки модулей.containers
а такжеcomponents
содержание.
Поэтому, когда мы обсуждаем, как организовать каталоги и файлы, это не имеет ничего общего с разделением компонентов на презентационные и контейнерные типы. То есть мы бы поместили все компоненты вcomponents
каталог, кроме страниц.
Несмотря на то, что нет необходимости разбивать их по каталогу, все же необходимо понимать различия между ними. Если у вас остались вопросы по этой теме, рекомендую прочитать эту статью:Presentational and Container Components.
Разделяйте и объединяйте код
существуетcomponents
В каталоге мы организуем файлы через структуру модуль/функция (module/feature).
В процессе добавления, удаления, изменения и проверки пользователей у нас будет только один модуль User. Таким образом, наша структура каталогов будет выглядеть так:
src
└─ components
└─ User
├─ Form.jsx
└─ List.jsx
Всякий раз, когда компонент имеет более одного файла, мы помещаем компонент и соответствующий ему файл в одну папку и называем его тем же именем. Например: теперь у нас естьForm.css
файл содержитForm.jsx
style, то наша структура каталогов будет выглядеть так:
src
└─ components
└─ User
├─ Form
│ ├─ Form.jsx
│ └─ Form.css
└─ List.jsx
Тестовый файл и тестовый файл объединяются в приведенном выше примере.
Form.jsx
Тестовые файлы будут помещены в ту же папку и названы какForm.spec.jsx
Компоненты пользовательского интерфейса
Помимо разделения компонентов по модулям, мы такжеsrc/components
разместитьUI
Каталог, используемый для хранения всех общих компонентов.
Компоненты пользовательского интерфейса не принадлежат какому-либо одному модулю и должны быть достаточно общими. Их можно размещать непосредственно в библиотеках с открытым исходным кодом, поскольку они не содержат какой-либо бизнес-логики, специфичной для приложения. Распространенными такими компонентами являются: кнопки, поля ввода, флажки, раскрывающиеся списки, модальные окна, компоненты визуализации данных и т. д.
именование компонентов
До сих пор мы видели, как организовать структуру каталогов и как разделить наши компоненты по модулям, но есть еще один вопрос: как их назвать?
Здесь мы говорим о том, как назвать наши классы или определить константы для компонентов.
class MyComponent extends Component {}
const MyComponent = () => {};
Имена компонентов должны быть понятными и уникальными в рамках приложения, что облегчает их поиск и позволяет избежать возможной путаницы.
Имя компонента очень удобно использовать при сбое приложения во время выполнения или при отладке через инструменты разработчика React, ведь место возникновения ошибки часто сопровождается названием компонента.
Мы используем именование компонентов на основе пути, то есть на основе относительногоcomponents
Относительный путь к каталогу с файлом, если он находится за пределами этой папки, используйте относительныйsrc
Путь к каталогу. Например, если путь компонентаcomponents/User/List.jsx
, то он называетсяUserList
.
Если имя файла и имя каталога файлов совпадают, нам не нужно повторять имя. То есть,components/User/Form/Form.jsx
будет названUserForm
вместоUserFormForm
.
Эта схема именования имеет следующие преимущества:
Удобный поиск файлов в проекте
Если ваш редактор поддерживает нечеткий поиск, просто найдитеUserForm
Это позволит вам найти соответствующий файл:
Если вы хотите найти файл в дереве каталогов, вы можете легко найти компонент по его имени:
Можно избежать дублирования имен при импорте
Следуя этому подходу, вы можете называть файлы в соответствии с контекстом компонента. Подумайте о компоненте формы выше, мы знаем, что это компонент формы в пользовательском модуле, но поскольку мы поместили компонент формы в каталог пользовательского модуля, нам не нужно повторять слово user в имени файла компонента формы, используйтеForm.jsx
Вот и все.
Когда я впервые использовал React, мне нравилось называть файлы полными именами, но это приводило к повторению одних и тех же частей слишком много раз, а пути импорта были слишком длинными. Давайте посмотрим на разницу между этими двумя методами:
import ScreensUserForm from './screens/User/UserForm';
// vs
import ScreensUserForm from './screens/User/Form';
В приведенном выше примере мы не видим явного преимущества. Но вы можете увидеть разницу, когда сложность приложения немного возрастет. Давайте посмотрим на следующий пример из моего реального проекта:
import MediaPlanViewChannel from '/MediaPlan/MediaPlanView/MediaPlanViewChannel.jsx';
// vs
import MediaPlanViewChannel from './MediaPlan/View/Channel';
Теперь представьте, что имя файла повторяется пять-десять раз.
По этой причине мы подумали, что лучше назвать файл компонента на основе его контекста и его относительного пути.
Страница (экран)
Если мы хотим добавлять, удалять, изменять и искать пользователя, нам нужна страница со списком пользователей, страница для создания новых пользователей и страница для редактирования существующих пользователей.
В приложении результатом объединения компонентов друг с другом является страница. В идеале страница не должна содержать никакой логики, а только функциональную составляющую.
мы начинаем сsrc
Каталог является корневым каталогом, а разные страницы разбросаны по разным папкам. Потому что они сгруппированы в соответствии с определениями маршрутов, а не модулями.
src
├─ components
└─ screens
└─ User
├─ Form.jsx
└─ List.jsx
Предполагая, что в нашем проекте используется react-router, мы помещаем файл Root.jsx в каталог screens и определяем все маршруты в нашем приложении.
Код для Root.jsx может выглядеть так:
import React, { Component } from 'react';
import { Router } from 'react-router';
import { Redirect, Route, Switch } from 'react-router-dom';
import ScreensUserForm from './User/Form';
import ScreensUserList from './User/List';
const ScreensRoot = () => (
<Router>
<Switch>
<Route path="/user/list" component={ScreensUserList} />
<Route path="/user/create" component={ScreensUserForm} />
<Route path="/user/:id" component={ScreensUserForm} />
</Switch>
</Router>
);
export default ScreensRoot;
Обратите внимание, что мы помещаем все страницы в один и тот же каталог, названный в честь маршрута. Попытайтесь создать каталог для каждого родительского маршрута, в котором организованы дочерние маршруты. В этом примере мы создали каталог пользователя и поместили в него страницу списка и страницу формы. Таким образом, вы можете легко найти страницу, отображаемую текущим маршрутом, одним взглядом на URL-адрес.
Подобно указанному выше маршруту для создания и редактирования пользователя, страница может отображаться при использовании двумя разными маршрутами.
Вы могли заметить, что все компоненты имеют префикс Screen в своих именах. Когда компоненты используются вне каталога компонентов, нам нужно назвать их, используя их путь относительно каталога src. родыsrc/screens/User/List.jsx
Компонент должен называться ScreensUserList.
Включая Root.jsx, наша структура каталогов выглядит следующим образом:
src
├─ components
└─ screens
├─ User
│ ├─ Form.jsx
│ └─ List.jsx
└─ Root.jsx
Не забудьте включить Root.jsx в качестве корневого компонента приложения в index.js.
Если вы все еще сомневаетесь, как выглядит страница, взгляните на пример ниже, это страница пользовательской формы.
import React from 'react';
import UserForm from '../../components/User/Form/Form';
const ScreensUserForm = ({ match: { params } }) => (
<div>
<h1>
{`${!params.id ? 'Create' : 'Update'}`} User
</h1>
<UserForm id={params.id} />
</div>
);
export default ScreensUserForm;
В конечном итоге структура каталогов нашего приложения будет выглядеть так:
src
├─ components
│ ├─ User
│ │ ├─ Form
│ │ │ ├─ Form.jsx
│ │ │ └─ Form.css
│ │ └─ List.jsx
│ └─ UI
│
└─ screens
├─ User
│ ├─ Form.jsx
│ └─ List.jsx
└─ Root.jsx
Точки обзора
- Презентационные и контейнерные компоненты размещаются в каталоге src/components.
- Организуйте компоненты по модулю/функции
- Основные компоненты пользовательского интерфейса размещаются в каталоге src/components/UI.
- Сохраняйте простоту страницы и используйте самую чистую структуру и код.
- Страницы организации определяются маршрутизацией. Для маршрута /user/list у нас будет страница /src/screens/User/List.jsx.
- Компоненты именуются путем относительно компонентов или src, т. е. компонент в src/components/User/List.jsx будет называться UserList. Компонент в src/screens/User/List.jsx будет называться ScreensUserList.
- Если компонент имеет то же имя, что и каталог, не повторяйте имя при использовании компонента. Рассмотрим сценарий, в котором компонент в src/components/User/List/List.jsx будет называться UserList вместо UserListList.