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:
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'
}
}
]
})2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Accessing Meta Fields โ
Access meta fields in components and navigation guards:
// 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 fields2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
๐ Practical Examples โ
Example 1: Authentication System โ
// 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`
}
})2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Example 2: Dynamic Layout System โ
// 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]
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
๐ง Advanced Meta Field Techniques โ
Nested Route Meta Inheritance โ
Child routes inherit meta fields from parent routes:
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
}
}
]
}
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
TypeScript Support โ
Add type safety to your meta fields:
// 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
}
}
]2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
๐ ๏ธ Real-World Implementations โ
Example 1: Breadcrumb Generation โ
// 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
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Example 2: Feature Flag System โ
// 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
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
๐ 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
๐ Related Features โ
- 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! ๐