Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Vue 3: Building Applications with Persistent Layouts and Route-Driven Content

Tech May 9 4

Modern web applications frequently require a persistent user interface layout where certain elements, such as a header, sidebar, or footer, remain constant while the main content area updates based on user interaction or routing. Vue Router in Vue 3 provides a straightforward mechanism to achieve this through its <router-view /> comopnent, allowing for dynamic content deliveyr within a static application shell.

The core of this pattern involves defining a root layout component that hosts the static UI elements and a designated placeholder for dynamic content. Typically, App.vue serves this purpose, acting as the primary container for the entire application. Within this component, global navigation elements, such as an el-menu from Element Plus, can be placed alongside a <router-view /> component. The <router-view /> component acts as a slot where the content of the currently matched route will be rendered.

Main Application Layout (App.vue)

This example demonstrates a horizontal navigation menu that controls the main content area. The activePath reactive variable ensures the correct menu item is highlighted based on the current URL path.

<template>
  <div class="application-wrapper">
    <header class="app-header">
      <img src="/path/to/your/logo.png" alt="Company Logo" class="app-logo" />
      <nav class="main-navigation">
        <el-menu
          :default-active="activePath"
          mode="horizontal"
          background-color="#2c3e50"
          text-color="#ecf0f1"
          active-text-color="#42b983"
          router
        >
          <el-menu-item index="/dashboard">Dashboard Overview</el-menu-item>
          <el-menu-item index="/products">Product Catalog</el-menu-item>
          <el-menu-item index="/customers">Customer Database</el-menu-item>
          <el-menu-item index="/analytics">System Analytics</el-menu-item>
          <el-menu-item index="/support">Support Center</el-menu-item>
          <el-menu-item>
            <a href="https://element-plus.org/" target="_blank" rel="noopener noreferrer">Element Plus Docs</a>
          </el-menu-item>
        </el-menu>
      </nav>
    </header>

    <main class="content-area">
      <router-view />
    </main>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';
import { useRoute } from 'vue-router';

// Access the current route object
const currentRoute = useRoute();

// Initialize activePath based on the current route's path
const activePath = ref(currentRoute.path);

// Watch for changes in the route path and update activePath
watch(() => currentRoute.path, (newPath) => {
  activePath.value = newPath;
});
</script>

<style scoped>
.application-wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.app-header {
  background-color: #2c3e50;
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
}
.app-logo {
  height: 40px;
  margin-right: 20px;
}
.main-navigation {
  flex-grow: 1;
  display: flex;
  justify-content: flex-end; /* Align menu items to the right */
}
.el-menu--horizontal {
  border-bottom: none; /* Remove default bottom border from Element Plus menu */
}
.content-area {
  flex-grow: 1;
  padding: 30px;
  background-color: #f8f9fa;
}
</style>

Route Configuration (src/router/index.js)

The <router-view /> component renders the component associated with the current route. To define these associations, a route configuration file (e.g., src/router/index.js) is used to map URL paths to specific Vue components. Each route object specifies a path, a name, and the component to render.

import { createRouter, createWebHistory } from 'vue-router';

// Import your application views/components
import DashboardPage from '../views/DashboardPage.vue';
import ProductsPage from '../views/ProductsPage.vue';
import CustomersPage from '../views/CustomersPage.vue';
import AnalyticsPage from '../views/AnalyticsPage.vue';
import SupportPage from '../views/SupportPage.vue';
import NotFoundPage from '../views/NotFoundPage.vue';

// Define the application routes
const applicationRoutes = [
  {
    path: '/',
    redirect: '/dashboard' // Redirect the root path to the dashboard
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: DashboardPage,
    meta: { title: 'Dashboard - App Admin' }
  },
  {
    path: '/products',
    name: 'Products',
    component: ProductsPage,
    meta: { title: 'Products - App Admin' }
  },
  {
    path: '/customers',
    name: 'Customers',
    component: CustomersPage,
    meta: { title: 'Customers - App Admin' }
  },
  {
    path: '/analytics',
    name: 'Analytics',
    component: AnalyticsPage,
    meta: { title: 'Analytics - App Admin' }
  },
  {
    path: '/support',
    name: 'Support',
    component: SupportPage,
    meta: { title: 'Support - App Admin' }
  },
  {
    // Catch-all route for any undefined paths
    path: '/:catchAll(.*)',
    name: 'NotFound',
    component: NotFoundPage,
    meta: { title: 'Page Not Found' }
  }
];

// Create the router instance
const router = createRouter({
  history: createWebHistory(), // Use HTML5 history mode
  routes: applicationRoutes,
});

// Optional: Navigation guard to update the document title
router.beforeEach((to, from, next) => {
  document.title = to.meta.title || 'App Admin Panel';
  next();
});

export default router;

When a user clicks on an el-menu-item (which utilizes router-link functionality when the router prop is true on el-menu), Vue Router intercepts the navigation request. It then identifies the component mapped to the target path in the applicationRoutes configuration and renders that component within the <router-view /> slot in App.vue. This design ensures that the header and navigation menu remain consistently visible and functional across different application views, creating a cohesive user experience while only the content area updates.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.