How to change page titles when using vue-router?

darkhorse picture darkhorse · Aug 1, 2018 · Viewed 27.4k times · Source

I would like to specify my titles within the route definition if possible. What is normally specified in <head><title> and appears in the browser title bar.

I have my project set up as follows:

main.js

import Vue from 'vue'
import App from './App.vue'
import VeeValidate from 'vee-validate';
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(VeeValidate);
Vue.use(ElementUI);
Vue.config.productionTip = false

new Vue({
    router,
    render: h => h(App)
}).$mount('#app')

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Skills from './components/Skills.vue'
import About from './components/About.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'skills',
      component: Skills,
      meta: { title: 'Skills - MyApp' } // <- I would to use this one
    },
    {
      path: '/about/:name',  // Add /:name here
      name: 'about',
      component: About,
      meta: { title: 'About - MyApp' }
    }
  ]
})

Preferably, I would want an automatic system instead of changing page title on the created function of every component. Thanks.

Answer

Steven B. picture Steven B. · Aug 1, 2018

You can use a navigation guard with the router definition:

import Vue from 'vue';

const DEFAULT_TITLE = 'Some Default Title';
router.afterEach((to, from) => {
    // Use next tick to handle router history correctly
    // see: https://github.com/vuejs/vue-router/issues/914#issuecomment-384477609
    Vue.nextTick(() => {
        document.title = to.meta.title || DEFAULT_TITLE;
    });
});

You'll need to change your export to:

const router = new Router({ ... });
...
export default router;

Or you can use an immediate watcher on your root component:

export default {
    name: 'App',
    watch: {
        $route: {
            immediate: true,
            handler(to, from) {
                document.title = to.meta.title || 'Some Default Title';
            }
        },
    }
};