Структура многостраничного приложения

Quasar Framework позволяет создавать высокопроизводительные многостраничные приложения (MPA) с использованием Vue.js. В основе организации многостраничного приложения лежит разделение логики по страницам, маршрутам и компонентам, что обеспечивает модульность, масштабируемость и удобство сопровождения кода.


1. Структура проекта

Стандартная структура многостраничного приложения в Quasar выглядит следующим образом:

src/
├── assets/           // Статические файлы: изображения, шрифты, стили
├── boot/             // Инициализация плагинов и библиотек
├── components/       // Переиспользуемые Vue-компоненты
├── layouts/          // Шаблоны страниц
├── pages/            // Страницы приложения
├── router/           // Настройки маршрутизации
└── store/            // Vuex или Pinia для управления состоянием

Ключевые моменты:

  • layouts содержат базовые шаблоны страниц, например MainLayout.vue с боковым меню и заголовком.
  • pages реализуют конкретные пользовательские интерфейсы.
  • router управляет переходами между страницами.
  • store обеспечивает централизованное управление состоянием приложения.

2. Настройка маршрутизации для MPA

Для многостраничного приложения важна корректная организация маршрутов. В Quasar используется Vue Router с поддержкой динамических маршрутов и lazy loading компонентов.

Пример файла router/routes.js:

const routes = [
  {
    path: '/',
    component: () => import('layouts/MainLayout.vue'),
    children: [
      { path: '', component: () => import('pages/IndexPage.vue') },
      { path: 'about', component: () => import('pages/AboutPage.vue') },
      { path: 'profile/:id', component: () => import('pages/ProfilePage.vue') }
    ]
  },
  {
    path: '/auth',
    component: () => import('layouts/AuthLayout.vue'),
    children: [
      { path: 'login', component: () => import('pages/LoginPage.vue') },
      { path: 'register', component: () => import('pages/RegisterPage.vue') }
    ]
  },
  { path: '/:catchAll(.*)*', component: () => import('pages/Error404.vue') }
]

export default routes

Особенности:

  • Использование children позволяет строить вложенные маршруты с общим макетом.
  • Lazy loading страниц через динамический импорт ускоряет первоначальную загрузку.
  • Поддержка параметров маршрута (profile/:id) обеспечивает динамическую подгрузку контента.

3. Layouts: каркас страниц

Layouts в Quasar отвечают за общую структуру интерфейса. Например, MainLayout.vue может включать:

<template>
  <q-layout view="lHh Lpr lFf">
    <q-header elevated>
      <q-toolbar>
        <q-toolbar-title>Приложение</q-toolbar-title>
      </q-toolbar>
    </q-header>

    <q-drawer v-model="drawer" show-if-above>
      <q-list>
        <q-item to="/" clickable>Главная</q-item>
        <q-item to="/about" clickable>О проекте</q-item>
      </q-list>
    </q-drawer>

    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script setup>
import { ref } from 'vue'
const drawer = ref(false)
</script>

Выводы по структуре Layouts:

  • q-layout задаёт каркас приложения.
  • q-header и q-drawer обеспечивают навигацию.
  • q-page-container содержит динамический контент страниц.

4. Pages: отдельные экраны приложения

Каждая страница хранится в src/pages и реализует конкретный UI. Пример IndexPage.vue:

<template>
  <q-page padding>
    <q-card>
      <q-card-section>
        Добро пожаловать на главную страницу!
      </q-card-section>
    </q-card>
  </q-page>
</template>

<script setup>
// Здесь можно подключить state или api
</script>

Замечания:

  • q-page используется внутри q-layout для корректного отображения контента.
  • Логика страницы должна быть минимально связана с другими страницами, чтобы сохранялась модульность.

5. Компоненты и переиспользуемость

Все элементы, которые повторяются на нескольких страницах (кнопки, карточки, таблицы), выносятся в src/components. Пример компонента:

<template>
  <q-btn :label="label" @click="$emit('click')" color="primary" />
</template>

<script setup>
defineProps({
  label: String
})
</script>

Принцип: компоненты должны быть атомарными и переиспользуемыми, без зависимости от конкретной страницы.


6. Управление состоянием

Quasar поддерживает Vuex и Pinia. Для MPA важно централизованное хранение состояния, чтобы страницы могли обмениваться данными. Пример Pinia Store:

import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    user: null
  }),
  actions: {
    login(payload) {
      this.user = payload
    },
    logout() {
      this.user = null
    }
  }
})

Преимущества:

  • Централизованное состояние упрощает работу с аутентификацией и настройками приложения.
  • Изменения состояния автоматически отражаются на всех страницах.

7. Асинхронная загрузка и оптимизация

Для больших приложений необходимо разделять код на чанки:

component: () => import('pages/ProfilePage.vue' /* webpackChunkName: "profile" */)

Эффекты:

  • Уменьшение начального размера бандла.
  • Подгрузка страниц по мере необходимости.
  • Повышение скорости загрузки и отзывчивости интерфейса.

8. Рекомендации по организации MPA

  • Каждая страница должна иметь собственный layout, если отличается структура.
  • Общие компоненты выносить в components.
  • Маршруты разделять на модули (auth, dashboard, settings) для удобства сопровождения.
  • Использовать lazy loading для всех страниц, кроме критичных.
  • Управление состоянием через Pinia/Vuex, чтобы избежать дублирования данных.

Эта структура обеспечивает чистоту кода, модульность и масштабируемость, что особенно важно при развитии крупных Quasar-приложений.