How can I bind the html <title> content in vuejs?

JavascriptHtmlMvvmFrontendvue.js

Javascript Problem Overview


I'm trying a demo on vuejs. Now I want the html title to bind a vm field.

The below is what I tried:

index.html

<!DOCTYPE html>
<html id="html">
<head>
    <title>{{ hello }}</title>
    <script src="lib/requirejs/require.min.js" data-main="app"></script>
</head>
<body>
{{ hello }}
<input v-model="hello" title="hello" />
</body>
</html>

app.js

define([    'jquery', 'vue'], function ($, Vue) {
    var vm = new Vue({
        el: 'html',
        data: {
            hello: 'Hello world'
        }
    });
});

But the title seemed not bounded, how to make it work?

Javascript Solutions


Solution 1 - Javascript

There are essentially two ways to solve it.

Use an existing Package

For example, vue-meta:

> >
>

Create your own Component

Create a vue file containing:

<script>
    export default {
        name: 'vue-title',
        props: ['title'],
        watch: {
            title: {
                immediate: true,
                handler() {
                    document.title = this.title;
                }
            }
        },
        render () {
        },
    }
</script>

Register the component using

import titleComponent from './title.component.vue';
Vue.component('vue-title', titleComponent);

Then you can use it in your templates, e.g.

<vue-title title="Static Title"></vue-title>
<vue-title :title="dynamic.something + ' - Static'"></vue-title>

Solution 2 - Javascript

You can do it with 1 line in the App.vue file, like this:

<script>
    export default {
        name: 'app',
        created () {
            document.title = "Look Ma!";
        }
    }
</script>

Or change the <title> tag content in public/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Look Ma!</title> <!- ------ Here ->
  </head>
...

Solution 3 - Javascript

This answer is for vue 1.x

using requirejs.

define([  'https://cdn.jsdelivr.net/vue/latest/vue.js'], function(Vue) {
  var vm = new Vue({
    el: 'html',
    data: {
      hello: 'Hello world'
    }
  });
});

<!DOCTYPE html>
<html id="html">

<head>
  <title>{{ hello }}</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.js" data-main="app"></script>
</head>

<body>
  {{ hello }}
  <input v-model="hello" title="hello" />
</body>

</html>

you can do it like this using the ready function to set the initial value and watch to update when the data changes.

<html>
<head>
<title>Replace Me</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <input v-model="title">
</div>


<script>
new Vue({
    el: '#app',
    ready: function () {
    	document.title = this.title
    },
    data: {
        title: 'My Title'
    },
    watch: {
    	title: function (val, old) {
    		document.title = val
    	}
    }
})
</script>

</body>
</html>

also i tried this based on your original code and it works

<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <input v-model="title">
</div>

<script>
new Vue({
    el: 'html',
    data: {
        title: 'My Title'
    }
})
</script>

</body>
</html>

Solution 4 - Javascript

Just to chime in here. I have read that VueJS wants nothing to do with the meta stuff so I would do such things outside of the "VueJS" realm.

Basically make a plain vanilla js service like below. Here you could add all the functions to handle the meta data stuff such as the Open Graph data.

meta.js

export setTitle(title) {
    document.title = title  
}

Now we can import the service in main and then provide it to any component in the app who wants it. I could even use my meta service in other projects too which use different frameworks like React or Angular. Portability is super cool!

main.js

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

Here the component injects the meta service it wants to use.

someView.vue

export default {
    name: 'someView',
    inject: ['meta'],
    data: function() {
        returns {
            title: 'Cool title'
        }
    },
    created: function() {
        this.meta.setTitle(this.title);
    }
}

This way the meta service is decoupled from the app because different parent components can provide different versions of the meta service. Now you can implement various strategies to see which one is right for you or even different strategies per component.

Basically the inject walks up the component hierarchy and takes the meta service from the first parent who provides it. As long as the meta service follows a proper interface, you're golden.

Decoupling with DI is super cool 

Solution 5 - Javascript

Title and meta tags can be edited and updated asynchronously.

You can use state management, create a store for SEO using vuex and update each part accordingly.

Or you can update the element by yourself easily

created: function() {  

  ajax().then(function(data){
     document.title = data.title  
     document.head.querySelector('meta[name=description]').content = data.description
  })
  
}

Solution 6 - Javascript

If you are using Vuex and want <title> to be part of your application state, then:

  • create a pageTitle state variable in Vuex
  • map the state to the template using mapState()
  • watch it in template, probably add immediate: true to trigger the watcher right away
  • in watcher, document.title = pageTitle

This will allow you to manage title with Vuex and keep them in sync. I found it useful for SPAs.

By doing this you don't have to mess with your original HTML template, as most of the time Vue root template resides inside <body>.

This is for Vue 2.x.

Solution 7 - Javascript

router.beforeEach((to, from, next) => {
  let mohican = to.path; if (mohican == '/') mohican = 'Home'
  document.title =  mohican.replace('/','');
  next();
 return;
});

Solution 8 - Javascript

I have an application toolbar component which is common for all pages of my SPA website and is nested in App.vue. In every page I update my common toolbar title in the created hook of the page using Vuex store:

//in every page.vue
created() {
  this.$store.commit('toolBar', { pageTitle: this.pageTitle, ...  })
},

To automatically update the website title (along with the toolbar title) I use this mutation in the store:

//store.js
toolBar(state,val){
  document.title = val.pageTitle
  state.toolBar = val
},

Similarly, I use the same mechanism to update e.g. SEO metadata

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlfred HuangView Question on Stackoverflow
Solution 1 - JavascriptstrView Answer on Stackoverflow
Solution 2 - JavascriptMonoThreadedView Answer on Stackoverflow
Solution 3 - JavascriptvbrandenView Answer on Stackoverflow
Solution 4 - Javascriptmr havenView Answer on Stackoverflow
Solution 5 - JavascriptserkanView Answer on Stackoverflow
Solution 6 - Javascriptdz902View Answer on Stackoverflow
Solution 7 - JavascriptDr.SaiView Answer on Stackoverflow
Solution 8 - JavascriptvessView Answer on Stackoverflow