логотип PurpleSchool
логотип PurpleSchool

Создание и структурирование Vue.js приложения

Автор

Ирина Лазарева

Введение

Vue.js считается одним из наиболее простых и мощных фреймворков для создания современных интерфейсов. Его гибкость позволяет разрабатывать как небольшие виджеты, так и масштабные приложения. Однако с ростом приложения вы можете столкнуться с вопросами организации кода, поддерживаемости и масштабируемости. Грамотно структурировать Vue.js проект — это фундамент для эффективной разработки и командной работы.

В этой статье я покажу вам, как создать Vue.js приложение с нуля и организовать проект так, чтобы вы могли развивать его без хаоса в кодовой базе. Вы узнаете, как правильно распределить файлы по папкам, как работать с компонентами, роутингом и состоянием приложения. Я приведу кодовые примеры и объясню детали каждого этапа.

Начальная инициализация Vue.js приложения

Выбор инструментов

Начинать рекомендую с официального инструмента Vue CLI или с Vite, который стал стандартом для новых Vue 3 проектов.

  • Vue CLI хорош для проектов с требованиями к большой кастомизации.
  • Vite обеспечивает молниеносную сборку и горячую перезагрузку, подходит для большинства задач.

Для примера возьмём Vite + Vue 3, так как это самый быстрый и актуальный способ.

Создание проекта с помощью Vite

Откройте терминал и выполните:

npm create vite@latest my-vue-app -- --template vue
  • my-vue-app — это ваша будущая папка с проектом.
  • Флаг --template vue указывает, что нужен шаблон Vue.

Далее:

cd my-vue-app
npm install
npm run dev

Теперь локальный сервер запущен, и вы видите стартовую страницу Vue-приложения.

Структура начального проекта

Давайте посмотрим, какие файлы вы получаете сразу:

my-vue-app/
├─ public/
│  └─ favicon.svg
├─ src/
│  ├─ assets/
│  ├─ components/
│  ├─ App.vue
│  └─ main.js
├─ index.html
├─ package.json
├─ vite.config.js

На этом скелете дальше строится архитектура реального приложения.

Развернутая структура приложения

Почему важна структура?

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

Базовая и расширенная структура

Предлагаю следующую схему, которую вы встретите во многих успешных проектах:

src/
├─ assets/          # Статические ресурсы (стили, изображения)
├─ components/      # Переиспользуемые компоненты
├─ views/           # Страницы приложения
├─ router/          # Файлы роутинга
├─ store/           # Централизованное состояние (Vuex, Pinia)
├─ services/        # Работа с API
├─ utils/           # Утилиты и хелперы
├─ composables/     # Композиционные функции (Vue 3)
├─ App.vue          # Корневой компонент
├─ main.js          # Точка входа

Давайте обсудим назначение каждой папки.

assets

Содержит изображения, иконки, стили и шрифты:

src/assets/logo.png
src/assets/styles/global.css

components

Здесь лежат микро-компоненты, которые можно использовать во многих местах, например, кнопки или карточки товаров:

src/components/BaseButton.vue
src/components/ProductCard.vue

views

Это страницы для роутинга. Например, главная и профиль пользователя:

src/views/HomeView.vue
src/views/ProfileView.vue

router

Здесь размещается настройка роутера:

src/router/index.js   // или router.js
Пример файла роутинга
// src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: HomeView
  },
  {
    path: '/profile',
    name: 'Profile',
    // Ленивая загрузка компонента
    component: () => import('../views/ProfileView.vue')
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

store

Здесь хранятся модули состояния. В Vue 3 чаще всего используется Pinia вместо Vuex.

Пример файла Pinia-стора
// src/store/user.js

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: '',
    authenticated: false
  }),
  actions: {
    login(name) {
      this.name = name
      this.authenticated = true
    },
    logout() {
      this.name = ''
      this.authenticated = false
    }
  }
})

services

Вынесите API-запросы и другую бизнес-логику.

// src/services/api.js

import axios from 'axios'

export function getUser(id) {
  // Получение информации о пользователе по id
  return axios.get(`/api/users/${id}`)
}

utils

Здесь находятся функции-помощники:

// src/utils/formatDate.js

export function formatDate(date) {
  // Преобразует дату в вид 'dd.mm.yyyy'
  const d = new Date(date)
  return `${d.getDate()}.${d.getMonth() + 1}.${d.getFullYear()}`
}

composables (в Vue 3)

В Vue 3 используются composables для повторного использования логики.

// src/composables/useToggle.js

import { ref } from 'vue'

export function useToggle(init = false) {
  // Возвращает реактивное состояние и функцию для его переключения
  const state = ref(init)
  function toggle() {
    state.value = !state.value
  }
  return { state, toggle }
}

Структура и написание компонентов

Однофайловые компоненты (Single File Components)

В Vue.js компонент обычно размещается в файле с расширением .vue. Такая структура делит компонент на три части:

  • <template> — шаблон разметки,
  • <script> — логика компонента,
  • <style> — непосредственные стили, часто с модификаторами scoped.

Пример простого компонента

<template>
  <button @click="increment">{{ count }}</button>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    // Создание реактивной переменной count
    const count = ref(0)
    function increment() {
      count.value++
    }
    return { count, increment }
  }
}
</script>

<style scoped>
button {
  padding: 10px 24px;
  font-size: 18px;
}
</style>

Организация крупных компонентов

Если компонент становится громоздким, разделите его на дочерние:

  • Вынесите части интерфейса или повторяющуюся логику в отдельные файлы в папке components/.
  • Используйте Base-префикс для базовых компонентов (BaseButton.vue, BaseInput.vue).

Использование props и событий

Vue-компоненты "общаются" между собой через props (пропсы) и события:

<!-- src/components/UserGreeting.vue -->
<template>
  <div @click="$emit('clicked')">Привет, {{ name }}!</div>
</template>

<script>
export default {
  props: {
    name: String
  }
}
</script>

Подключение роутинга и состояния

Роутинг: переход между страницами

В файле main.js регистрируем роутер:

// src/main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App)
  .use(router)
  .mount('#app')

Состояние: глобальный store

Для глобального состояния современный выбор — Pinia:

// src/main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'

const app = createApp(App)

app.use(createPinia())
app.use(router)
app.mount('#app')

Теперь вы можете использовать store в компонентах:

import { useUserStore } from '../store/user'

export default {
  setup() {
    const user = useUserStore()
    // user.login('Ирина')
    // user.logout()
    return { user }
  }
}

Организация стилей и ассетов

Использование глобальных, модульных и scoped-стилей

  • global.css кладём в assets и импортируем один раз в main.js.
  • В каждом компоненте используйте <style scoped>, если стили применимы только к этому компоненту.
  • Применяйте CSS-модули, если нужно исключить конфликты стилей в больших проектах.

Работа с ассетами

Импортировать изображения можно прямо в шаблонах или скриптах:

<template>
  <img :src="logo" alt="Логотип" />
</template>
<script>
import logo from '../assets/logo.png'

export default {
  setup() {
    return { logo }
  }
}
</script>

Тестирование и best practices

Где размещать тесты

Локализуйте тесты рядом с файлами компонентов или внутри отдельной папки tests/.

src/components/
  ├─ BaseButton.vue
  └─ __tests__/
       └─ BaseButton.spec.js

Советы по организации кода

  • Соблюдайте принцип "однофайловых компонентов": всё, что относится к одному компоненту — в одном файле.
  • Не копируйте код, а выносите повторяемую логику в composables или утилиты.
  • Именуйте компоненты в PascalCase (UserProfile.vue).
  • Используйте папки для модулей — по фичам и доменам для больших приложений.

Заключение

Создание Vue.js приложения начинается с грамотной и продуманной структуры — это обеспечивает максимум удобства и адаптивности проекта при его развитии. Используя современные инструменты вроде Vite и Pinia, комбинируя компоненты, роутинг, глобальное состояние и четкую структуру директорий, вы делаете приложение поддерживаемым и легким для расширения. Деление по принципу "views–components–store–services–utils–composables" позволит избежать хаоса в будущем, особенно если проект быстро растет или вы работаете в команде.


Частозадаваемые технические вопросы по теме статьи и ответы на них

1. Как подключить стороннюю библиотеку компонентов (например, Element Plus) в проекте на Vue 3?

Ответ:
Установите библиотеку через npm:
npm install element-plus
Импортируйте нужные компоненты и css в main.js:
```js import ElementPlus from 'element-plus' import 'element-plus/dist/index.css'

const app = createApp(App) app.use(ElementPlus) ``` Теперь вы можете использовать компоненты Element Plus в шаблонах.


2. Что делать, если роутер не работает — ссылки не меняют страницу?

Ответ:
Убедитесь, что вы правильно используете <router-view /> в App.vue, а навигацию осуществляете с помощью <router-link> или $router.push(). Проверьте, что пути указываются правильно в файле routes, и что роутер зарегистрирован в main.js через app.use(router).


3. Как работать с environment-переменными в Vite/Vue?

Ответ:
Создайте файл .env (или .env.local) в корне проекта.
Переменные должны начинаться с VITE_, например:
VITE_API_URL=https://api.example.com
В коде эти значения доступны через import.meta.env.VITE_API_URL.


4. Где лучше размещать глобальные фильтры и как их реализовать в Vue 3?

Ответ:
Вместо фильтров из Vue 2 используйте функции (например, в src/utils). Импортируйте и используйте их в компонентах либо регистрируйте как глобальные методы через provide/inject или app.config.globalProperties.


5. Как настроить абсолютные пути для импортов, чтобы не писать '../../../'?

Ответ:
В Vite настройте поле resolve.alias в файле vite.config.js:
js import { fileURLToPath, URL } from 'node:url' export default defineConfig({ resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } }) Теперь можно импортировать, например, @/components/MyComponent.vue.


Стрелочка влевоРабота со стилями и CSS в Vue js для красивых интерфейсовКак исправить ошибку cannot find module vueСтрелочка вправо

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий