Компонент Vue и исходные данные команды
Оглавление серии «Vue 3: кабинет сотрудников «Команда»»
В кабинете «Команда» руководитель просматривает сотрудников, находит нужную роль и уточняет доступность участника. Начнём с самого малого результата: данные трёх вымышленных людей должны стать текстом страницы через компонент Vue. Вы уже знаете элементы HTML, массивы, объекты и импорт JavaScript. Здесь важнее понять границу между данными и представлением, чем заранее раскладывать небольшой экран по десяткам папок.
Серия использует Vue 3.5.43 и формат Single File Component. Сопутствующие версии находятся в package.json архива: они фиксируют профиль чтения документации, но ещё не являются проверенной установкой. В отличие от обычного скрипта с ручным поиском элементов, компонент описывает, какое содержимое следует получить из модели. Руководство Vue о SFC объясняет объединение шаблона, логики и оформления в одном файле.
Данные и точка входа
Базовое состояние архива содержит index.html, src/main.js, настройки Vite и src/data/members.js. В последнем файле записаны Анна, Павел и Ирина. У каждого есть устойчивый id, name, role, available и version. Идентификатор относится к человеку, а не к его позиции в массиве. Поле version пока остаётся равным единице; оно понадобится при разборе серверного конфликта. Такое предварительное поле не требует отдельного механизма уже сейчас.
Посмотрите на main.js до изменения компонента. createApp получает корневой компонент и mount связывает его с элементом app. Сам контейнер объявлен в HTML, а данные в него попадают через шаблон. Если идентификатор контейнера изменить только в одном месте, приложение не получит ожидаемую точку монтирования. Поэтому «страница открылась» и «компонент подключился» обозначают разные обстоятельства: документ может существовать без содержимого кабинета.
Ниже полный новый файл src/App.vue. Имена импортированы из общего массива, а шаблон использует свойства объекта member в каждой строке.
<script setup>
import { seedMembers } from './data/members.js'
</script>
<template>
<main>
<h1>Команда</h1>
<p>Участников: {{ seedMembers.length }}</p>
<ul>
<li v-for="member in seedMembers" :key="member.id">
<strong>{{ member.name }}</strong> — {{ member.role }}
<span>{{ member.available ? 'Доступен' : 'Занят' }}</span>
</li>
</ul>
</main>
</template>
Ожидаемая страница содержит заголовок «Команда», число три и три строки. Анна и Ирина отмечены доступными, Павел занят. Здесь нет загрузки из сети, входа пользователя или долговременного хранения. Обновление исходного массива в редакторе меняет учебные данные, а перезагрузка страницы заново создаёт приложение. Эти границы позволят позже отличить реактивное изменение в памяти от подтверждённого изменения серверной записи.
Как читается шаблон
В script setup импорт доступен шаблону без дополнительного объекта return. Это специальный синтаксис SFC, который обрабатывает инструмент сборки. Браузер самостоятельно не понимает расширение vue; поэтому открыть App.vue как отдельный HTML-файл недостаточно. Архив описывает локальную подготовку окружения, но никаких команд установки при написании серии не выполнялось. Не переносите содержимое script setup в тег script статической страницы, ожидая того же поведения.
Интерполяция в двойных фигурных скобках превращает выражение в текст. Тернарное выражение выбирает одну из двух подписи доступности. Мы не храним эти подписи рядом с available: иначе одно поле могло бы говорить true, а другое по ошибке оставаться «Занят». Булево значение является исходными данными, текст — его представлением. Позже перевод интерфейса сможет изменить подпись без изменения договорённости о формате сотрудника.
Директива v-for повторяет элемент li для каждого объекта. Атрибут :key передаёт выражение JavaScript, тогда как key="member.id" передал бы одинаковую буквальную строку. На первом неподвижном экране эта разница может остаться незаметной. Когда список начнёт сортироваться или получать новые записи, корректный ключ поможет Vue сопоставлять прежние строки с теми же участниками. Отдельный урок покажет, почему индекс массива не подходит для этого договора.
В шаблоне уместны короткие выражения, помогающие прочитать вывод. Если поиск, сортировка и подбор подписи превратятся в цепочку условий внутри одной строки, причину результата будет трудно объяснить. Поэтому не будем прямо сейчас добавлять в фигурные скобки фильтрацию массива. Вычисляемые свойства появятся тогда, когда действительно возникнет зависимый список. Последовательность введения понятий здесь совпадает с последовательностью изменений нашего кабинета.
Текст сотрудника и граница HTML
Попробуйте мысленно заменить имя Анны на строку, содержащую уголки и название тега. Через интерполяцию оно должно остаться видимым текстом, а не новым элементом интерфейса. Для имён и должностей это правильный договор: пользователь вводит значение поля, а не программу разметки. Документация синтаксиса шаблонов различает текстовую интерполяцию и вывод HTML через v-html.
Значимая ошибка этого шага — желание поставить v-html на name ради «более гибкого имени». Такой приём изменяет смысл поля и создаёт возможность внедрения чужой разметки. Для кабинета обычная текстовая модель лучше: выделение имени делает собственный strong в шаблоне. Таким образом оформление остаётся в компоненте, а данные сотрудника сохраняют простой формат. Потребность в богатом описании потребовала бы отдельного правила очистки, которого в этой серии нет.
Обратите внимание и на доступность. Список сотрудников использует ul и li, заголовок задаёт название страницы, доступность написана словами. Если заменить «Занят» только красной точкой, часть читателей лишится значения состояния. Позже кнопки будут менять доступность, но их текст также останется предметным. Уже первый экран задаёт принцип: важный смысл должен читаться по структуре документа и тексту, а не зависеть от декоративного цвета.
Перед следующим шагом вы должны уметь связать конкретный фрагмент страницы с конкретным свойством исходного объекта. Для самостоятельного разбора добавьте в копию массива четвёртого вымышленного участника и заранее запишите ожидаемое число и подпись. Если число меняется, а строка отсутствует, проверьте используемый массив и место шаблона. Следующий урок добавит изменение доступности во время работы компонента и покажет, что именно Vue должен наблюдать.
Граница ответственности корневого компонента
Корневой компонент сейчас и получает данные, и описывает весь экран. Это удобно для первого результата: путь от массива к странице виден в одном месте. Разделять его стоит тогда, когда появится самостоятельный договор карточки или формы. Если вынести каждый элемент раньше, объяснение начнёт зависеть от связей, ещё не нужных читателю. Наш первый файл позволяет проверить начальную модель до появления таких связей.
Для самостоятельного воспроизведения результата «Показать трёх участников в одном SFC» выберите lesson-01 в архиве исходников. Статус выполнения этого состояния: not_run.