-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how to change document.title in vue-router? #914
Comments
Hi, thanks for filling this issue. You can simply define title in route's router.beforeEach((to, from, next) => {
document.title = to.meta.title
next()
}) The author of the PR closed it himself, so we don't know why. But setting title is trivially easy to implement with current API. |
This seems like it would cover it, but what if the title should be dynamic, based on the content of the loaded component? |
I change the title in created hook for dynamic title |
Does the dynamic title persist in the browser's history? @dengyaolong |
{ |
@fnlctrl Setting the title to a static value seems easy using 'meta'. I guess I could just set document.title manually in the component, but that seems like a workaround. Is there a hook that can access the matched component? |
It is possible if you define the title attribute as a function : {
meta: { title: route => { /* return custom title based on route, store or anything */ } }
} and router.beforeEach((to, from, next) => {
document.title = to.meta.title(to)
next()
}) |
I've got a solution and used it on one of my projects. First create a directive. Vue.directive('title', {
inserted: (el, binding) => document.title = binding.value,
update: (el, binding) => document.title = binding.value
}) Then use that directive on the Suppose, we are working on <router-view v-title="title" ></router-view> export default {
data(){
return {
title: 'This will be the title'
}
}
} This works even if the component is updated or the page is reloaded. |
@yTakkar nice solution. You can also give the title as a value for the directive like this:
and then in the directive definition: Vue.directive('title', {
inserted: (el,binding) => document.title = binding.value,
update: (el,binding) => document.title = binding.value
}) But unfortunately couldn't make it work when I have nested routes. Did you find a solution for this? Or maybe you don't have in your project nested routes. |
@aocneanu I updated the answer!! |
1st, this scenario worked for me too, but try to add another component in the upper level and switch between that component and a child of notes. 2nd, I'm not sure that your use of (multiple times for multiple components) is correct. In my app I have a single component for all the components from one level. 3rd, this approach has a problem because for every component update the document title will be updated as well, even if it's not necessary. I know it's not a big thing but I don't like when my code does redundant stuff. Try add a console.log in the directive and see how many hits it gets, even if you don't switch the page. 4th, I ended using the router.beforeEach() method and it works seamlessly. |
I've just come across the same thing and found vue-meta. |
combinging @fnlctrl and @RodrigoAngeloValentini 's solutions solved my problems. thanks |
I created a component to do that from the view. It is similar to yTakkar's solution but more complete in that you also can set the description, keywords, language and some other things (mostly useful when doing server-side rendering). It is called vue-headful and you can use it as follows:
Every attribute is also reactive, see vue-headful for more information. vue-headful is based on Headful, a vanilla JavaScript library to set document title and meta tags with JavaScript. |
@troxler This is very nice component, thank you! |
For all who are struggling, too. I used @yTakkar's way and expanded it with the route name.
|
Thanks! I find solution for me created () { |
A plugin can help.
Then calling |
My little solution for handling routes with params (dynamic): router.beforeEach((to, from, next) => {
let title = to.name;
const keys = Object.keys(to.params);
if (keys.length) {
title = `${to.name}: ${to.params[keys[0]]}`;
if (to.params[keys[1]]) {
title += ` ${to.params[keys[1]]}`;
}
}
document.title = title;
next();
}); |
To get it to work with browser history (in history mode) I had to modify @Waals code. The problem with I think all of the above approaches is that they change the title before the browser's history is updated. This leaves you with history that is off-by-one. Ie if you start
If you clicked To fix this we need to wait until after the router navigation before updating the document title. This code works: Route configuration gets meta.title {
meta: { title: route => { /* return custom title based on route, store or anything */ } }
} and then set document title in nextTick in afterEach. router.afterEach((to, from) => {
Vue.nextTick(() => {
document.title = to.meta.title(to)
})
}) To reference the Vue docs on navigation guards:
Ideally we would want to update the title at step 12, but we can't access it with global hooks :(.. |
Here is what i came up with: I'm using a base title + extension for every route. The title is localized with vue-i18n. With this approach the title will persist in the history. Also upon locale-change the title will change to the new locale too. App.vue <template>
<div></div>
</template>
<script>
export default {
name: 'App',
components: {
},
data () {
return {
}
},
computed: {
cWindowTitle () {
// route-name is part of the localisation-key
const routeName = this.$route.name
const home = routeName === 'home'
let title = this.$t('windowTitle.base')
if (!home) {
// only add title extension if this is not the main/home route
title = `${title} - ${this.$t(`windowTitle.${routeName}`)}`
}
return title
}
},
watch: {
cWindowTitle: 'setWindowTitle'
},
created () {
this.setWindowTitle()
},
methods: {
setWindowTitle () {
document.title = this.cWindowTitle
}
}
}
</script> |
add this to
|
Tackles #3 This can be improved, see: vuejs/vue-router#914 (comment)
With Vue 3 I am ended with this solution without the nextTick:
My index.js file
|
I really want set title when I declare routes. e.g
then title will change by the vue-router.
how ?
ps, I see the pull issue closed. why?
#526
The text was updated successfully, but these errors were encountered: