forked from ddrilling/asb_cloud_front
171 lines
11 KiB
Markdown
171 lines
11 KiB
Markdown
## 1. Общие положения
|
||
1. Все несамостоятельные компоненты должны быть написаны на TypeScript. Для самостоятельных компонентов (использующихся как страницы) (далее страницы) допускается использование JavaScript для ускорения написания;
|
||
|
||
### 1.1. Файловая структура проекта
|
||
1. Компоненты должны распределяться по директориям в соответствии со своим назначением:
|
||
* `src/context` - Для контекстов приложения;
|
||
* `src/components` - Для несамостоятельных компонентов, применяющихся многократно;
|
||
* `src/pages` - Для страниц и компонентов, использующихся исключительно в единственном экземпляре;
|
||
* `src/images` - Для компонентов-изображений.
|
||
2. Если страница описывается 1 файлом она должна именоваться в соответствии с содержимым, в ином случае должна быть создана директория с соответствующим названием, внутри которой будут находиться файлы страницы. Основной файл в таком случае должен быть переименован в `index.jsx`;
|
||
3. Файлы именуются в соответствии с таблицей:
|
||
| Тип содержимого файла | Расширение | Стиль именования |
|
||
|--------------------------------------|------------|--------------------------|
|
||
| Компонент или страница | jsx/tsx | **PascalCase** |
|
||
| Файл стилей | css/less | **snake_case** |
|
||
| Вспомогательные методы или константы | js/ts | **snake_case** |
|
||
| Описательные документы | md | **SCREAMING_SNAKE_CASE** |
|
||
|
||
### 1.2. Стилизация кода
|
||
1. Все строки должны по возможности описываться одинарными кавычками или при необходимости обратными:
|
||
```js
|
||
const name = 'world'
|
||
const msg = 'Hello, \'' + name + '\'!'
|
||
const toPrint = `Message: ${msg}`
|
||
```
|
||
2. Все переменные по возможности должны инициализироваться как `const`, применение `var` не допускается;
|
||
3. Переменные именуются в соответствии с таблицей:
|
||
| Тип переменной | Стиль именования |
|
||
|-------------------|--------------------------|
|
||
| Метод, переменная | **camelCase** |
|
||
| Константы | **SCREAMING_SNAKE_CASE** |
|
||
| Компонент | **PascalCase** |
|
||
|
||
### 1.3. Импортирование / Экспортирование
|
||
1. Импортированные файлы (в том числе lazy import) необходимо указывать в самом верху документа в следующем порядке с разделением пустой строкой:
|
||
1. Внешние зависимости (`react`, `antd`, `webpack` и т.д.);
|
||
2. Локальные компоненты по порядку:
|
||
1. Контексты (`@asb/context`);
|
||
2. Компоненты (`@components/Table`);
|
||
3. Вспомогательные методы (`@utils`);
|
||
4. Сервисы API (`@api`).
|
||
3. Изображения и компоненты-изображения (`@images`);
|
||
4. Стили (`@styles`);
|
||
5. Lazy import (`const page = React.lazy(() => import('./page'))`).
|
||
2. При импорте локальных файлов стоит пользоваться alias'ами:
|
||
| Путь | Alias |
|
||
|------------------|--------------|
|
||
| src/components | @components |
|
||
| src/context | @asb/context |
|
||
| src/images | @images |
|
||
| src/pages | @pages |
|
||
| src/services/api | @api |
|
||
| src/styles | @styles |
|
||
| src/utils | @utils |
|
||
3. По возможности импортировать из пакетов и файлов только использующиеся сущности:
|
||
```tsx
|
||
// вместо
|
||
import React from 'react'
|
||
const page: React.ReactNode = React.lazy(() => import (...))
|
||
|
||
// стоит использовать
|
||
import { lazy, ReactNode } from 'react'
|
||
const page: ReactNode = lazy(() => import (...))
|
||
```
|
||
|
||
## 2. JS
|
||
1. Методы, константы и переменные документируются в соответствии с `JSDoc`;
|
||
2. При документации страниц необходимо указать её название, краткое описание и описание получаемых параметров:
|
||
```jsx
|
||
import { memo } from 'react'
|
||
|
||
import LoaderPortal from '@components/LoaderPortal'
|
||
|
||
/**
|
||
* Тестовая страница
|
||
*
|
||
* @description Данная страница не имеет смысла и просто выводит переданное название и контент
|
||
* @param title - Название страницы
|
||
* @param content - Контент страницы
|
||
* @param loading - Отображать ли оверлей загрузки над блоком страницы
|
||
*/
|
||
export const TestPage = memo(({ title, content, loading }) => (
|
||
<LoaderPortal show={loading}>
|
||
<div className={'dd-test-page'}>
|
||
<div className={'dd-test-page-title'}>{title}</div>
|
||
<div className={'dd-test-page-content'}>{content}</div>
|
||
</div>
|
||
</LoaderPortal>
|
||
))
|
||
|
||
export default TestPage
|
||
```
|
||
|
||
## 3. TS
|
||
1. Методы, константы и переменные документируются в соответствии с `TSDoc`;
|
||
2. При документации компонентов необходимо указать их название, краткое описание, а также описать параметры в типе:
|
||
```tsx
|
||
import { memo } from 'react'
|
||
|
||
import LoaderPortal from '@components/LoaderPortal'
|
||
|
||
export type TestPageProps = {
|
||
/** Название страницы */
|
||
title: ReactNode
|
||
/** Контент страницы */
|
||
content: ReactNode
|
||
/** Отображать ли оверлей загрузки над блоком страницы */
|
||
loading: boolean
|
||
}
|
||
|
||
/**
|
||
* Тестовая страница
|
||
*
|
||
* @description Данная страница не имеет смысла и просто выводит переданное название и контент
|
||
*/
|
||
export const TestPage = memo<TestPageProps>(({ title, content, loading }) => (
|
||
<LoaderPortal show={loading}>
|
||
<div className={'dd-test-page'}>
|
||
<div className={'dd-test-page-title'}>{title}</div>
|
||
<div className={'dd-test-page-content'}>{content}</div>
|
||
</div>
|
||
</LoaderPortal>
|
||
))
|
||
|
||
export default TestPage
|
||
```
|
||
3. Использование `any` в типах допустимо только, если значение используется только в параметрах компонентов, обозначенных типом `any`. Если метод предполагает работу с разными типами значений стоит описать его как обобщённый.
|
||
|
||
|
||
## 4. JSX/TSX
|
||
|
||
### 4.1. Стилизация кода
|
||
1. Все указываемые к компоненту параметры должны быть обёрнуты в фигурные скобки, кроме параметров флагов со значением `true`:
|
||
```jsx
|
||
<Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
|
||
```
|
||
2. Если описание параметров компонента не укладывается в ширину в 120 строк стоит перенести их в соответствии с шаблоном:
|
||
```jsx
|
||
<Button
|
||
disabled
|
||
title={'Hello, world!'}
|
||
type={'ghost'}
|
||
>
|
||
Click me!
|
||
</Button>
|
||
```
|
||
3. Если JSX код передаётся как значение стоит обернуть его в круглые скобки:
|
||
```jsx
|
||
const a = (
|
||
<Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
|
||
)
|
||
```
|
||
|
||
### 4.2. Логика поведения
|
||
1. Не допускается создание значений ссылочных типов в области рендера. Они должны быть вынесены в переменные или константы;
|
||
2. Не допускается создание переменных в функциональных компонентов без использования хуков `useMemo`/`useCallback`/`useState`;
|
||
3. Если переменные или методы не имеют зависимостей и не вызывают методы, доступные исключительно внутри компонента, они должны быть вынесены выше кода компонента.
|
||
|
||
|
||
## 5. LESS
|
||
1. Использование id должно быть сведено к минимуму;
|
||
2. Все классы именуются с префиксом компании "`dd-`";
|
||
3. Слова в классах разделяются тире ("`-`");
|
||
4. Файлы именуются в соответствии с компонентом, к которому относятся;
|
||
5. В одном файле описываются стили либо к конкретному компоненту, либо к странице;
|
||
6. Файл со стилями должен подключаться не более чем к одному компоненту (странице);
|
||
7. Файлы поделены на директории виду компонента, к которому применяются стили:
|
||
* `styles/components` - для компонентов, не использующихся самостоятельно;
|
||
* `styles/pages` - для компонентов, использующихся как страница;
|
||
* `styles/widgets` - для компонентов, применяющихся как виджеты в дашбордах.
|