Skip to content

Route Meta Fields | Vue Router - Add Custom Data to Your Routes ๐Ÿ“‹ โ€‹

Enhanced route configuration - Attach custom data and behavior to your routes!

๐ŸŽฏ Overview โ€‹

Route meta fields allow you to attach arbitrary information to route records. This powerful feature enables various advanced scenarios like authentication guards, breadcrumb generation, page titles, and layout selection.

๐Ÿ“‹ Common Use Cases โ€‹

  • Authentication & Authorization: Protect routes based on user roles
  • Layout Selection: Choose different layouts for different routes
  • Page Metadata: Set titles, descriptions, and other SEO information
  • Breadcrumb Generation: Automatically generate navigation breadcrumbs
  • Feature Flags: Enable/disable routes based on feature toggles

๐Ÿ’ก Basic Meta Field Usage โ€‹

Defining Meta Fields โ€‹

Add meta fields to your route configuration:

javascript
const router = createRouter({
  routes: [
    {
      path: '/admin',
      component: AdminLayout,
      meta: {
        requiresAuth: true,
        requiresAdmin: true,
        title: 'Admin Dashboard'
      }
    },
    {
      path: '/profile',
      component: UserProfile,
      meta: {
        requiresAuth: true,
        title: 'User Profile'
      }
    },
    {
      path: '/public',
      component: PublicPage,
      meta: {
        public: true,
        title: 'Public Information'
      }
    }
  ]
})

Accessing Meta Fields โ€‹

Access meta fields in components and navigation guards:

javascript
// In navigation guards
router.beforeEach((to, from) => {
  if (to.meta.requiresAuth && !isAuthenticated()) {
    return '/login'
  }
  
  if (to.meta.requiresAdmin && !isAdmin()) {
    return '/unauthorized'
  }
})

// In components
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.meta.title) // Access meta fields

๐Ÿš€ Practical Examples โ€‹

Example 1: Authentication System โ€‹

javascript
// Route configuration with auth meta
const routes = [
  {
    path: '/',
    component: Home,
    meta: { public: true, title: 'Home' }
  },
  {
    path: '/login',
    component: Login,
    meta: { public: true, title: 'Login' }
  },
  {
    path: '/dashboard',
    component: Dashboard,
    meta: { 
      requiresAuth: true,
      title: 'Dashboard'
    }
  },
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      requiresAdmin: true,
      title: 'Admin Panel'
    }
  }
]

// Navigation guard
router.beforeEach((to, from) => {
  // Check authentication requirements
  if (to.meta.requiresAuth && !isAuthenticated()) {
    // Redirect to login with return URL
    return {
      path: '/login',
      query: { redirect: to.fullPath }
    }
  }
  
  // Check admin permissions
  if (to.meta.requiresAdmin && !isAdmin()) {
    return '/unauthorized'
  }
  
  // Set page title
  if (to.meta.title) {
    document.title = `${to.meta.title} - My App`
  }
})

Example 2: Dynamic Layout System โ€‹

javascript
// Layout components
const Layouts = {
  default: () => import('./layouts/Default.vue'),
  admin: () => import('./layouts/Admin.vue'),
  auth: () => import('./layouts/Auth.vue'),
  minimal: () => import('./layouts/Minimal.vue')
}

// Route configuration
const routes = [
  {
    path: '/',
    component: Home,
    meta: { layout: 'default', title: 'Home' }
  },
  {
    path: '/login',
    component: Login,
    meta: { layout: 'auth', title: 'Login' }
  },
  {
    path: '/admin',
    component: Admin,
    meta: { layout: 'admin', title: 'Admin' }
  },
  {
    path: '/privacy',
    component: Privacy,
    meta: { layout: 'minimal', title: 'Privacy Policy' }
  }
]

// App component with dynamic layout
const App = {
  template: `
    <component :is="currentLayout">
      <RouterView />
    </component>
  `,
  computed: {
    currentLayout() {
      const layout = this.$route.meta.layout || 'default'
      return Layouts[layout]
    }
  }
}

๐Ÿ”ง Advanced Meta Field Techniques โ€‹

Nested Route Meta Inheritance โ€‹

Child routes inherit meta fields from parent routes:

javascript
const routes = [
  {
    path: '/user',
    component: UserLayout,
    meta: { requiresAuth: true },
    children: [
      {
        path: 'profile',
        component: UserProfile,
        // Inherits requiresAuth: true from parent
        meta: { title: 'User Profile' }
      },
      {
        path: 'settings',
        component: UserSettings,
        // Can override parent meta
        meta: { 
          requiresAuth: true, // Explicitly set
          title: 'User Settings',
          requiresVerification: true // Additional requirement
        }
      }
    ]
  }
]

TypeScript Support โ€‹

Add type safety to your meta fields:

typescript
// types/router.d.ts
import 'vue-router'

declare module 'vue-router' {
  interface RouteMeta {
    // Authentication
    requiresAuth?: boolean
    requiresAdmin?: boolean
    requiresVerification?: boolean
    
    // Layout
    layout?: 'default' | 'admin' | 'auth' | 'minimal'
    
    // SEO
    title?: string
    description?: string
    keywords?: string[]
    
    // Features
    featureFlags?: string[]
    
    // Custom
    [key: string]: any
  }
}

// Now you get type checking and autocomplete
const routes: RouteRecordRaw[] = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      requiresAdmin: true,
      title: 'Admin', // โœ… Type checked
      layout: 'admin' // โœ… Type checked
      // invalidField: true // โŒ Type error
    }
  }
]

๐Ÿ› ๏ธ Real-World Implementations โ€‹

Example 1: Breadcrumb Generation โ€‹

javascript
// Route configuration with breadcrumb meta
const routes = [
  {
    path: '/',
    component: Home,
    meta: { 
      title: 'Home',
      breadcrumb: 'Home'
    }
  },
  {
    path: '/products',
    component: ProductList,
    meta: { 
      title: 'Products',
      breadcrumb: 'Products'
    },
    children: [
      {
        path: ':category',
        component: ProductCategory,
        meta: { 
          title: 'Category',
          breadcrumb: 'Category' // Dynamic value set in component
        }
      },
      {
        path: ':category/:productId',
        component: ProductDetail,
        meta: { 
          title: 'Product Details',
          breadcrumb: 'Product Details'
        }
      }
    ]
  }
]

// Breadcrumb component
const Breadcrumb = {
  template: `
    <nav class="breadcrumb">
      <ol>
        <li v-for="(crumb, index) in breadcrumbs" :key="index">
          <RouterLink 
            v-if="crumb.to" 
            :to="crumb.to"
            :class="{ active: !crumb.to }"
          >
            {{ crumb.title }}
          </RouterLink>
          <span v-else>{{ crumb.title }}</span>
        </li>
      </ol>
    </nav>
  `,
  computed: {
    breadcrumbs() {
      const crumbs = []
      this.$route.matched.forEach((route, index) => {
        if (route.meta.breadcrumb) {
          crumbs.push({
            title: route.meta.breadcrumb,
            to: index < this.$route.matched.length - 1 ? route.path : null
          })
        }
      })
      return crumbs
    }
  }
}

Example 2: Feature Flag System โ€‹

javascript
// Route configuration with feature flags
const routes = [
  {
    path: '/',
    component: Home,
    meta: { title: 'Home' }
  },
  {
    path: '/new-feature',
    component: NewFeature,
    meta: { 
      title: 'New Feature',
      featureFlags: ['new-feature-enabled']
    }
  },
  {
    path: '/beta',
    component: Beta,
    meta: { 
      title: 'Beta Features',
      featureFlags: ['beta-access']
    }
  }
]

// Feature flag check in navigation guard
router.beforeEach((to, from) => {
  const requiredFlags = to.meta.featureFlags || []
  
  for (const flag of requiredFlags) {
    if (!isFeatureEnabled(flag)) {
      // Redirect to feature unavailable page
      return '/feature-unavailable'
    }
  }
})

// Utility function to check feature flags
function isFeatureEnabled(flagName) {
  // Check against your feature flag system
  return window.featureFlags && window.featureFlags[flagName] === true
}

๐Ÿ” Meta Field Best Practices โ€‹

โœ… Do โ€‹

  • Use Descriptive Names: Clear, meaningful meta field names
  • Keep It Simple: Avoid overly complex meta structures
  • Document Your Meta Fields: Maintain documentation for team members
  • Use TypeScript: Get type safety and autocomplete
  • Test Meta Field Logic: Ensure guards work correctly

โŒ Don't โ€‹

  • Overuse Meta Fields: Not everything needs to be in meta
  • Store Large Data: Meta should be lightweight
  • Ignore Inheritance: Understand how child routes inherit meta
  • Forget Defaults: Provide sensible defaults where possible
  • Navigation Guards: Use meta fields for route protection
  • Route Records: Understand the route matching system
  • Route Params: Combine with dynamic route parameters
  • Route Query: Use with URL query parameters

๐Ÿ’ก Pro Tip

Combine route meta fields with Vue's provide/inject API to create a powerful configuration system that can be accessed throughout your component tree!

Ready to enhance your routes? Start using meta fields to add powerful, customizable behavior to your Vue Router configuration! ๐Ÿ“‹

๐Ÿš€ Vue Router - ่ฎฉๅ‰็ซฏ่ทฏ็”ฑๅ˜ๅพ—็ฎ€ๅ•่€Œๅผบๅคง | ๆž„ๅปบ็ŽฐไปฃๅŒ–ๅ•้กตๅบ”็”จ็š„ๆœ€ไฝณ้€‰ๆ‹ฉ