使用 vue-router 时如何更改页面标题?
How to change page titles when using vue-router?
如果可能的话,我想在路线定义中指定我的头衔。通常在 <head><title>
中指定并显示在浏览器标题栏中的内容。
我的项目设置如下:
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' }
}
]
})
最好,我想要一个自动系统,而不是在每个组件的创建函数上更改页面标题。谢谢
您可以使用具有路由器定义的导航守卫:
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;
});
});
您需要将导出更改为:
const router = new Router({ ... });
...
export default router;
或者您可以在您的根组件上使用直接观察者:
export default {
name: 'App',
watch: {
$route: {
immediate: true,
handler(to, from) {
document.title = to.meta.title || 'Some Default Title';
}
},
}
};
我想补充一点,上面并没有真正保留历史。请参阅 https://github.com/vuejs/vue-router/issues/914#issuecomment-384477609 以获得更好的实际处理历史的答案(尽管有点老套)。
实际上,根据我对 Steven B. 解决方案的实验,我想出了一些更好的方法。事情是这样的
watch: {
$route(to, from) {
document.title = to.meta.title || 'Some Default Title';
},
}
当我们最初访问该页面时(通过浏览器的地址栏导航)不起作用。相反,我们可以像这样创建一个 getter:
computed: {
pageTitle: function() {
return this.$route.meta.title;
}
}
现在,在我的例子中,我正在寻找设置 "template" 的 header(这样 children 路由就不会为此烦恼)就是这样;对于您的情况,您可能想知道如何在计算 属性 后设置文档的标题,并且有 some ways。根据这些答案,您甚至可以:
created () {
document.title = this.$route.meta.title;
}
但在生产中使用之前,我会针对重新访问同一页面(不确定是否每次都创建该组件)的情况进行测试。
我发现这个解决方案使用了 mixins 并且需要最少的代码。
https://medium.com/@Taha_Shashtari/the-easy-way-to-change-page-title-in-vue-6caf05006863 and originally https://github.com/vuejs/vue-hackernews-2.0/blob/master/src/util/title.js
我喜欢它,因为您可以在视图组件而不是路线中定义标题:
在 src/mixins 目录中创建一个名为 titleMixin.js 的新文件,内容如下。它正在检查组件的 'title' 属性 的值是否为变量或函数以及 returns title 变量的值或return title() 函数的值。
function getTitle (vm) {
const { title } = vm.$options
if (title) {
return typeof title === 'function'
? title.call(vm)
: title
}
}export default {
created () {
const title = getTitle(this)
if (title) {
document.title = title
}
}
}
在您的 main.js 中全局注册 mixin。在创建 Vue 实例之前添加:
import titleMixin from './mixins/titleMixin'
Vue.mixin(titleMixin)
最后,在视图组件文件中(例如 Home.vue )使用名为 title 的 属性 来定义页面标题。
export default {
name: 'Home',
title: 'Homepage Title',
components: {
...
}
}
一个小缺陷:mixin 是全局注册的,这使得 mixin 可用于 所有 组件,即使对于 non view 组件也是如此没有意义。
高级变体
使用 vue-meta
首先运行
npm install vue-meta
并将其添加到您的 main.js;
import VueMeta from 'vue-meta'
Vue.use(VueMeta)
这样做之后,您可以向 每个 vue 组件 添加一个 metaInfo()
方法,处理元数据;
metaInfo() {
return {
title: "Epiloge - Build your network in your field of interest",
meta: [
{ name: 'description', content: 'Epiloge is about connecting in your field of interest. Our vision is to help people share their knowledge, work, projects, papers and ideas and build their network through what they do rather where they live, study or work.'},
{ property: 'og:title', content: "Epiloge - Build your network in your field of interest"},
{ property: 'og:site_name', content: 'Epiloge'},
{property: 'og:type', content: 'website'},
{name: 'robots', content: 'index,follow'}
]
}
}
此外,这可用于 动态元信息;
export default{
name: 'SingleUser',
data(){
return{
userData: {},
...
aws_url: process.env.AWS_URL,
}
},
metaInfo() {
return {
title: `${this.userData.name} - Epiloge`,
meta: [
{ name: 'description', content: 'Connect and follow ' + this.userData.name + ' on Epiloge - ' + this.userData.tagline},
{ property: 'og:title', content: this.userData.name + ' - Epiloge'},
{ property: 'og:site_name', content: 'Epiloge'},
{ property: 'og:description', content: 'Connect and follow ' + this.userData.name + ' on Epiloge - ' + this.userData.tagline},
{property: 'og:type', content: 'profile'},
{property: 'og:url', content: 'https://epiloge.com/@' + this.userData.username},
{property: 'og:image', content: this.aws_url + '/users/' + this.userData.profileurl + '-main.jpg' }
]
}
},
...
}
来源:Medium - How to add dynamic meta-tags to your Vue.js app for Google SEO
2021 年最新作品方式- Vue3:
在.\router\index.js
中添加相关组件的行名
{
path: '/',
name: 'Home page'
},
在BeforeEach里加载这个函数也写在.\router\index.js
router.beforeEach((to, from, next) => {
document.title = to.name;
next();
});
对于 Vue 3:
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(config.publicPath),
routes,
});
const DEFAULT_TITLE = 'Some Default Title';
router.beforeEach((to) => {
document.title = to.meta.title || DEFAULT_TITLE;
});
我正在寻找编辑标题但不一定要使用路由器。我发现使用 mounted 方法也可以做到。
new Vue({
mounted: function() {
document.title = 'WOW VUE TITLE'
}
})
哦再看一个包
我在这里看到了很多很棒的解决方案,但我提交的可能会失败:https://www.npmjs.com/package/@aminoeditor/vue-router-seo
它小于 1mb,没有依赖性并且具有灵活的实现,所有这些都可以在您的路由配置中轻松控制。它还具有对 title
和其他元数据的异步支持。
基本示例
import { seoGuardWithNext } from '@aminoeditor/vue-router-seo';
const routes = [{
path: '/',
component: Home,
meta: {
seo: {
title: 'My title here',
metaTags: [
{
name: 'description',
content: 'My Description here'
},
{
name: 'keywords',
content: 'some,keywords,here'
}
],
richSnippet: {
"@context": "https://schema.org",
"@type": "Project",
"name": "My Project",
"url": "https://exampl.com",
"logo": "https://example.com/images/logo.png",
"sameAs": [
"https://twitter.com/example",
"https://github.com/example"
]
}
}
}
},{
path: '/about',
component: About,
meta: {
seo: {
// do some async stuff for my page title
title: async route => {
const data = await fetch('somedataurl');
return `${data} in my title!`;
}
}
}
}]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes,
})
// install the seo route guard here
router.beforeEach(seoGuardWithNext)
const app = Vue.createApp({})
app.use(router)
app.mount('#app')
由于页面标题经常重复视图中的一些文本内容(例如页面上的header),我建议使用directive来完成此任务。
const updatePageTitle = function (title) {
document.title = title + ' - My Cool Website';
};
Vue.directive('title', {
inserted: (el, binding) => updatePageTitle(binding.value || el.innerText),
update: (el, binding) => updatePageTitle(binding.value || el.innerText),
componentUpdated: (el, binding) => updatePageTitle(binding.value || el.innerText),
});
在每个视图中,您可以决定将哪些元素内容视为浏览器标题:
<h1 v-title>Some static and {{ dynamic }} title</h1>
或者您可以在指令值内构建标题:
<div v-title="'Some static and ' + dynamic + 'title'">...</div>
如果可能的话,我想在路线定义中指定我的头衔。通常在 <head><title>
中指定并显示在浏览器标题栏中的内容。
我的项目设置如下:
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' }
}
]
})
最好,我想要一个自动系统,而不是在每个组件的创建函数上更改页面标题。谢谢
您可以使用具有路由器定义的导航守卫:
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;
});
});
您需要将导出更改为:
const router = new Router({ ... });
...
export default router;
或者您可以在您的根组件上使用直接观察者:
export default {
name: 'App',
watch: {
$route: {
immediate: true,
handler(to, from) {
document.title = to.meta.title || 'Some Default Title';
}
},
}
};
我想补充一点,上面并没有真正保留历史。请参阅 https://github.com/vuejs/vue-router/issues/914#issuecomment-384477609 以获得更好的实际处理历史的答案(尽管有点老套)。
实际上,根据我对 Steven B. 解决方案的实验,我想出了一些更好的方法。事情是这样的
watch: {
$route(to, from) {
document.title = to.meta.title || 'Some Default Title';
},
}
当我们最初访问该页面时(通过浏览器的地址栏导航)不起作用。相反,我们可以像这样创建一个 getter:
computed: {
pageTitle: function() {
return this.$route.meta.title;
}
}
现在,在我的例子中,我正在寻找设置 "template" 的 header(这样 children 路由就不会为此烦恼)就是这样;对于您的情况,您可能想知道如何在计算 属性 后设置文档的标题,并且有 some ways。根据这些答案,您甚至可以:
created () {
document.title = this.$route.meta.title;
}
但在生产中使用之前,我会针对重新访问同一页面(不确定是否每次都创建该组件)的情况进行测试。
我发现这个解决方案使用了 mixins 并且需要最少的代码。
https://medium.com/@Taha_Shashtari/the-easy-way-to-change-page-title-in-vue-6caf05006863 and originally https://github.com/vuejs/vue-hackernews-2.0/blob/master/src/util/title.js
我喜欢它,因为您可以在视图组件而不是路线中定义标题:
在 src/mixins 目录中创建一个名为 titleMixin.js 的新文件,内容如下。它正在检查组件的 'title' 属性 的值是否为变量或函数以及 returns title 变量的值或return title() 函数的值。
function getTitle (vm) {
const { title } = vm.$options
if (title) {
return typeof title === 'function'
? title.call(vm)
: title
}
}export default {
created () {
const title = getTitle(this)
if (title) {
document.title = title
}
}
}
在您的 main.js 中全局注册 mixin。在创建 Vue 实例之前添加:
import titleMixin from './mixins/titleMixin'
Vue.mixin(titleMixin)
最后,在视图组件文件中(例如 Home.vue )使用名为 title 的 属性 来定义页面标题。
export default {
name: 'Home',
title: 'Homepage Title',
components: {
...
}
}
一个小缺陷:mixin 是全局注册的,这使得 mixin 可用于 所有 组件,即使对于 non view 组件也是如此没有意义。
高级变体
使用 vue-meta
首先运行
npm install vue-meta
并将其添加到您的 main.js;
import VueMeta from 'vue-meta'
Vue.use(VueMeta)
这样做之后,您可以向 每个 vue 组件 添加一个 metaInfo()
方法,处理元数据;
metaInfo() {
return {
title: "Epiloge - Build your network in your field of interest",
meta: [
{ name: 'description', content: 'Epiloge is about connecting in your field of interest. Our vision is to help people share their knowledge, work, projects, papers and ideas and build their network through what they do rather where they live, study or work.'},
{ property: 'og:title', content: "Epiloge - Build your network in your field of interest"},
{ property: 'og:site_name', content: 'Epiloge'},
{property: 'og:type', content: 'website'},
{name: 'robots', content: 'index,follow'}
]
}
}
此外,这可用于 动态元信息;
export default{
name: 'SingleUser',
data(){
return{
userData: {},
...
aws_url: process.env.AWS_URL,
}
},
metaInfo() {
return {
title: `${this.userData.name} - Epiloge`,
meta: [
{ name: 'description', content: 'Connect and follow ' + this.userData.name + ' on Epiloge - ' + this.userData.tagline},
{ property: 'og:title', content: this.userData.name + ' - Epiloge'},
{ property: 'og:site_name', content: 'Epiloge'},
{ property: 'og:description', content: 'Connect and follow ' + this.userData.name + ' on Epiloge - ' + this.userData.tagline},
{property: 'og:type', content: 'profile'},
{property: 'og:url', content: 'https://epiloge.com/@' + this.userData.username},
{property: 'og:image', content: this.aws_url + '/users/' + this.userData.profileurl + '-main.jpg' }
]
}
},
...
}
来源:Medium - How to add dynamic meta-tags to your Vue.js app for Google SEO
2021 年最新作品方式- Vue3:
在.\router\index.js
{
path: '/',
name: 'Home page'
},
在BeforeEach里加载这个函数也写在.\router\index.js
router.beforeEach((to, from, next) => {
document.title = to.name;
next();
});
对于 Vue 3:
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(config.publicPath),
routes,
});
const DEFAULT_TITLE = 'Some Default Title';
router.beforeEach((to) => {
document.title = to.meta.title || DEFAULT_TITLE;
});
我正在寻找编辑标题但不一定要使用路由器。我发现使用 mounted 方法也可以做到。
new Vue({
mounted: function() {
document.title = 'WOW VUE TITLE'
}
})
哦再看一个包
我在这里看到了很多很棒的解决方案,但我提交的可能会失败:https://www.npmjs.com/package/@aminoeditor/vue-router-seo
它小于 1mb,没有依赖性并且具有灵活的实现,所有这些都可以在您的路由配置中轻松控制。它还具有对 title
和其他元数据的异步支持。
基本示例
import { seoGuardWithNext } from '@aminoeditor/vue-router-seo';
const routes = [{
path: '/',
component: Home,
meta: {
seo: {
title: 'My title here',
metaTags: [
{
name: 'description',
content: 'My Description here'
},
{
name: 'keywords',
content: 'some,keywords,here'
}
],
richSnippet: {
"@context": "https://schema.org",
"@type": "Project",
"name": "My Project",
"url": "https://exampl.com",
"logo": "https://example.com/images/logo.png",
"sameAs": [
"https://twitter.com/example",
"https://github.com/example"
]
}
}
}
},{
path: '/about',
component: About,
meta: {
seo: {
// do some async stuff for my page title
title: async route => {
const data = await fetch('somedataurl');
return `${data} in my title!`;
}
}
}
}]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes,
})
// install the seo route guard here
router.beforeEach(seoGuardWithNext)
const app = Vue.createApp({})
app.use(router)
app.mount('#app')
由于页面标题经常重复视图中的一些文本内容(例如页面上的header),我建议使用directive来完成此任务。
const updatePageTitle = function (title) {
document.title = title + ' - My Cool Website';
};
Vue.directive('title', {
inserted: (el, binding) => updatePageTitle(binding.value || el.innerText),
update: (el, binding) => updatePageTitle(binding.value || el.innerText),
componentUpdated: (el, binding) => updatePageTitle(binding.value || el.innerText),
});
在每个视图中,您可以决定将哪些元素内容视为浏览器标题:
<h1 v-title>Some static and {{ dynamic }} title</h1>
或者您可以在指令值内构建标题:
<div v-title="'Some static and ' + dynamic + 'title'">...</div>