Динамические layouts

Quasar Framework предоставляет гибкую систему layouts, которая позволяет создавать многоуровневую и динамическую структуру интерфейсов. Основная идея заключается в том, что layout — это каркас страницы, включающий в себя навигацию, хедер, футер и основные контейнеры для контента. Динамические layouts позволяют изменять эти структуры в зависимости от состояния приложения, роли пользователя или маршрута.


Основные концепции

  • Layout как компонент Vue: каждый layout — это полноценный Vue-компонент, поэтому в нем можно использовать все возможности Vue, включая реактивные свойства, вычисляемые значения и методы.
  • Router View: динамические layouts тесно связаны с router-view. В зависимости от маршрута или состояния можно подгружать разные layouts, не дублируя основной код приложения.
  • Slots и QPageContainer: QPageContainer используется внутри layout для размещения содержимого страницы. С помощью слотов можно вставлять динамические панели, виджеты и другие компоненты.

Динамическая смена layout по маршруту

Quasar позволяет задавать layout непосредственно в объекте маршрута:

const routes = [
  {
    path: '/admin',
    component: () => import('layouts/AdminLayout.vue'),
    children: [
      { path: '', component: () => import('pages/AdminDashboard.vue') }
    ]
  },
  {
    path: '/user',
    component: () => import('layouts/UserLayout.vue'),
    children: [
      { path: '', component: () => import('pages/UserHome.vue') }
    ]
  }
];

Здесь каждый маршрут использует свой layout. Это позволяет создавать различные интерфейсы для администраторов и обычных пользователей, не дублируя страницы.


Управление layout через состояние приложения

Для более гибкой логики можно переключать layout динамически через реактивное состояние:

<template>
  <component :is="currentLayout">
    <router-view />
  </component>
</template>

<script>
import AdminLayout from 'layouts/AdminLayout.vue';
import UserLayout from 'layouts/UserLayout.vue';
import { ref, computed } from 'vue';

export default {
  setup() {
    const userRole = ref('user'); // или 'admin'

    const currentLayout = computed(() => {
      return userRole.value === 'admin' ? AdminLayout : UserLayout;
    });

    return { currentLayout };
  }
};
</script>

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


Интерактивные и адаптивные компоненты в layout

Quasar предлагает множество готовых компонентов, которые могут менять своё поведение в зависимости от layout:

  • QDrawer: боковое меню, которое можно скрывать или раскрывать динамически.
  • QHeader / QFooter: заголовок и подвал могут менять высоту, цвет и видимые элементы в зависимости от контента или состояния пользователя.
  • QPageScroller / QPageSticky: позволяют создавать динамические интерактивные элементы, которые остаются на экране при прокрутке страницы.

Пример адаптивного layout с drawer:

<template>
  <q-layout view="lHh Lpr lFf">
    <q-header elevated>
      <q-toolbar>
        <q-btn flat round icon="menu" @click="toggleDrawer" />
        <q-toolbar-title>Dashboard</q-toolbar-title>
      </q-toolbar>
    </q-header>

    <q-drawer v-model="drawerOpen" show-if-above>
      <q-list>
        <q-item clickable v-for="item in menuItems" :key="item.label">
          <q-item-section>{{ item.label }}</q-item-section>
        </q-item>
      </q-list>
    </q-drawer>

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

<script>
import { ref } from 'vue';

export default {
  setup() {
    const drawerOpen = ref(false);
    const menuItems = ref([
      { label: 'Главная' },
      { label: 'Профиль' },
      { label: 'Настройки' }
    ]);

    const toggleDrawer = () => {
      drawerOpen.value = !drawerOpen.value;
    };

    return { drawerOpen, toggleDrawer, menuItems };
  }
};
</script>

Совмещение динамических и условных layouts

Иногда необходимо менять не весь layout целиком, а лишь его части, например хедер или боковое меню:

<template>
  <q-layout view="lHh Lpr lFf">
    <q-header v-if="isLoggedIn">
      <q-toolbar>Личный кабинет</q-toolbar>
    </q-header>
    <q-header v-else>
      <q-toolbar>Гость</q-toolbar>
    </q-header>

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

<script>
import { computed } from 'vue';
import { useUserStore } from 'stores/user';

export default {
  setup() {
    const userStore = useUserStore();
    const isLoggedIn = computed(() => userStore.loggedIn);

    return { isLoggedIn };
  }
};
</script>

Такой подход позволяет строить гибкие интерфейсы с разными элементами управления для разных пользователей, минимизируя дублирование кода.


Практические рекомендации

  1. Разделять layouts по ролям и функционалу, чтобы избежать чрезмерной сложности одного файла.
  2. Использовать динамические компоненты Vue для переключения layouts без перезагрузки.
  3. Внутри layout использовать QPageContainer и слоты, чтобы страницы могли изменяться независимо от каркаса.
  4. Применять реактивные свойства и computed, чтобы управлять отображением элементов интерфейса на лету.
  5. Следить за оптимизацией загрузки, импортируя layouts лениво через import().

Динамические layouts Quasar предоставляют мощный инструмент для создания адаптивных и персонализированных интерфейсов, сочетая возможности Vue, маршрутизации и готовых UI-компонентов. Они позволяют легко управлять структурами страниц, снижая дублирование кода и повышая масштабируемость приложений.