Angular vs React глазами новичка

Kate

Administrator
Команда форума
В 2021 году на рынке фронтенд-технологий лидируют React, Angular и, с некоторым отставанием, Vue. В нашей компании для унификации подбора разработчиков сделан упор на React, но ряд крупных систем разрабатываются с помощью современных версий Angular. В связи с конкуренцией этих технологий возникло желание изучить каждую из них и составить собственное мнение о применимости этих инструментов.

Как будем сравнивать?​

Для начала попробуем написать на Angular простое приложение. Перед этим предлагаю прочитать базовые моменты из документации и пройти «Тур Героев». Получив основные навыки и взяв «Тур героев» за основу разработаем своё первое приложение на Angular и React, сравнив субьективные преимущества и недостатки.

Описание проекта​

В качестве первого приложения отлично подходят проекты вроде «список задач», «блог» или «учёт расходов». Чтобы не повторяться, попробуем создать приложение для выявления автобусного фактора в команде. Bus-фактор — то количество людей в проекте, внезапное исчезновение которых (например, из-за ДТП с автобусом) приведёт к остановке или значительному замедлению различных процессов.

Приложение по аналогии с «Туром героев» будет состоять из главной dashboard-страницы, страницы с управлением навыками и сотрудниками, и с детализированными страницами по каждому навыку и сотруднику. Текущий дизайн приложения далёк от совершенства, основная цель — изучить логику работы с Angular и React при создании приложения.

На главной странице в MVP приложения выводим самых критичных сотрудников, чьи навыки надо забирать всей остальной команде

a3ad1633a2c9b423efb1d06baff4d41e.png

На странице с управлением навыками и сотрудниками мы увидим две колонки, в каждую из которых можно добавить новый навык или указать имя нового сотрудника. Навыком может быть как знание какой-то критически важной технологии, так и глубокое понимание работы того или иного микросервиса или фронт-проекта, эксплуатируемого командой. Для каждого навыка отображается, сколько сотрудников его знают, а для каждого сотрудника — количество освоенных им навыков.

1b0bf96573eceeef9b48d06121524130.png

Страницы с детализацией навыков и сотрудников похожи: на них можно отредактировать название навыка или имя сотрудника, а также нажатием на элемент из списка пометить, что сотрудник изучил навык (тогда красный восклицательный знак сменится на зелёную галочку).

671eedf38ca05afde6093b8bf096bc17.png

Попробовать проект вживую можно вот тут: https://bus-factor.web.app, ссылка на кодовую базу — https://github.com/domclick/bus_factor

Описание кодовой базы и принятых решений​

Чтобы при проектировании приложения не отвлекаться на написание любимого бекенда, был выбран Google Firebase как представитель Backend-as-a-service. Структура данных для проекта выглядит так:

403403f3129deb96a0d3b4d2adede618.png

Всего две сущности — «Сотрудники» и их «Навыки», и таблица для прикрепления навыка к сотруднику. Для взаимодействия с этими сущностями были написаны мы написали Angular-сервисы, которые реализуют необходимый CRUD для общения с Firebase-бекендом:

Код

Описанный выше дизайн было решено реализовать на следующем наборе компонентов:

dashboard

Главная страница довольно простая, уместилась в один компонент. Чтобы одновременно загрузить данные и по сотрудникам, и по их связанным навыкам, используем forkJoin из rxjs. Полученные данные подготавливаем с помощью набора циклов и сортировки (которые наверняка можно было написать оптимальней), и получаем следующий файл:

Код
bus-factor-list

Страница для управления навыками и сотрудниками использует компоненты skill-item и employee-item. Для получения событий из дочерних компонентов и реакции на них используем директиву Output, обработав полученные данные в handleDeleteSkill и handleDeleteEmployee.

Код
В целом код для сущностей «Сотрудник» и «Навык» в MVP очень похож, но я не стал убирать дублирование кода, потому что в дальнейшем каждый компонент будет кастомизироваться. Typescript-логика для bus-factor-list выглядит так:

Код
skill-item

Для того, чтобы просклонять в зависимости от численности слово «сотрудник», был использован pipe pluralize:

Код
В компонент skill-item он подключается следующим образом:

<div class="skill-container" (click)="onSkillClick()">
<div class="skill-info">
<div class="skill-name">{{ skill.name }}</div>
<div class="skill-skills">
{{ skillCount }} {{ skillCount | pluralize: ['сотрудник', 'сотрудника', 'сотрудников'] }}
</div>
</div>
<button class="delete" title="delete skill"
(click)="deleteSkill(skill)">
Удалить
</button>
</div>
Внутри Typescript-логики можно увидеть использование события Output:

Код
skill-detail и employee-detail

На страницах с управлением навыками каждого сотрудника (employee-detail), а также на странице с редактированием навыка и списком сотрудников, обладающим этим навыком (skill-detail) можно увидеть использование директивы ng-template в else-блоке отображения наличия/отсутствия навыка:

<div class="card-title">Управление навыком</div>
<div class="skill-info">
<div class="skill-id"></div>
<input [(ngModel)]="skill.name" placeholder="Название навыка"/>
<div class="skill-controls">
<button (click)="goBack()">Назад</button>
<button (click)="save()">Сохранить</button>
</div>
</div>
<div class="skill-box">
<div class="skills-title">Сотрудники с этим навыком</div>
<div class="skill" *ngFor="let employee of employees" (click)="changeEmployeeSkill(employee.id)">
<img src="assets/icons/done.svg" *ngIf="employeeIdsHasSkill.includes(employee.id); else noSkill">
<ng-template #noSkill><img class="square-img" src="assets/icons/icon_warning_red.svg"></ng-template>
<div class="skill-name"> {{employee.name}}</div>
</div>
</div>
header и sidebar

Довольно типовые для большинства проектов блоки, код можно посмотреть в исходниках проекта.

Что дальше?​

qyvapkr1sohj0ankoaxr_mnlfru.png

Прототип приложения на Angular написан, базовые навыки получены. Теперь можно приступить к React-проекту либо углубить текущий Angular-прототип, добавив в него авторизацию, админку, профили пользователей, красивые графики и прочую функциональность. Либо поработать с бекендом, заменив Firebase на полноценный микросервис на чём-нибудь современном, например, на fastAPI.

 
Сверху