How to define variables in Vue router to be used inside components?

Viewed 1439

I have a navbar on top and a <router-view> right below it (as seen in App.vue). I want the title inside the navbar to change depending on the route/view I am on. Since my views in the <router-view> do not contain the title itself, I need to define them somewhere. An example for the scenario could be when reaching the route /login, the title in the navbar changes to "Login". How do I achieve this?

When searching for a solution, I came across a lot of page title questions. I am not talking about the document.title assignment, however, that could be a solution, but not a perfect one. What if I wanted the title to be something else than the document title..

App.vue:

<template>
  <Menu :isActive="isMenuActive" />
  <Navbar @toggle:hamburger="onHamburgerToggle($event)" />
  <router-view />
</template>
2 Answers

Vue router allows you to attach any information you want to any route using Route Meta Fields

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { title: "FOO" }
    }      
  ]
})

You can access the information for currently active route in any component using $route variable

const child = Vue.component('child', {
  template: `
  <div>
    Child component ("{{ $route.meta.title }}")
  </div>
  `
})

const router = new VueRouter({
  mode: 'history',  
  routes: [
    {
      name: 'route1',
      path: '/route1',
      component: child,
      meta: { title: 'Hello from route 1!'}
    },    
    {
      name: 'route2',
      path: '/route2',
      component: child,
      meta: { title: 'Hello from route 2!'}
    },    
  ]
})

new Vue({
  el: '#app',
  router,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
  <router-link to="/route1">Route 1</router-link>
  <router-link to="/route2">Route 2</router-link>
  
  <h4> Current route: {{ $route.meta.title }} </h4>

  <router-view></router-view>
</div>

Every component can access the $route object, so you could use that directly in your template. Or you can access that object in the script and do something with it.

Imagine your routes have the name property:

router/index.js

routes: [
  { path: '/', name: 'home', component: Home },
  { path: '/foo', name: 'foo', component: Foo },
  { path: '/bar', name: 'bar', component: Bar }
]

You could show that name in the template with no script necessary:

Navbar.vue

<template>
  <div>Title: {{ $route.name }}</div>
</template>

(meta is also a good idea here as explained in @MichalLevĂ˝'s answer.)

Or you could access the route object in the script and create a title however you want.

Navbar.vue (Composition API)

<template>
  <div>Title: {{ title }}</div>
</template>
<script>
import { ref } from 'vue';
import { useRoute } from 'vue-router';

export default {
  setup() {
    const route = useRoute();
    const title = ref('My title ' /* Do something with `route` */);
    return { title }
  }
}
</script>
Related