Vue路由器:如何为动态路由动态生成页面标题?
Vue router: How to dynamically generate page titles for dynamic routes?
我有一个使用 Vue CLI 创建的简单 Vue-based 网站,我正在尝试弄清楚如何为带有动态路由的视图动态生成页面标题。该站点正在从无头 CMS 中提取 JSON 数据,并且我为“项目”内容类型的详细视图设置了动态路由。我将动态路由设置如下:
// single project vue (dynamic)
{
path: "/projects/:project_name_slug",
name: "single-project",
component: () =>
import(
/* webpackChunkName: "single-project" */ "./views/SingleProject.vue"
),
meta: {
title: "project detail",
}
}
我添加了以下内容,可用于添加静态页面标题:
// show page titles
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
// document.title = to.meta.title || DEFAULT_TITLE;
document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});
按照目前的情况,在访问项目详细信息视图时,标题将显示为“我的博客 - 项目详细信息”;但是,我希望它从 project_name
的 JSON/field 数据中提取实际项目名称(就像路由路径使用 project_name_slug
一样),但到目前为止我还没有尝试过已经工作了。例如,使用 meta: { title: (route) => route.params.project_name }
只会导致原始函数文本显示在“我的博客 - ”之后。因此,对于那些动态视图,我希望 to.meta.title
解析为项目名称,创建“我的博客 - {项目名称}”。感谢您在这里提供的任何帮助,如果我需要提供更多详细信息,请告诉我。
*注意:这个问题与 中提出的问题不同,因为我的案例涉及使用通过 Axios
请求的 JSON 数据的动态路由
在路由器的beforeEach
导航守卫中设置meta
:
router.beforeEach((to, from, next) => {
to.meta.title = to.params.project_name_slug;
next();
});
-或-
您可以使用 beforeRouteEnter
和 beforeRouteUpdate
in-component guards:
export default {
...
beforeRouteEnter(to, from, next) {
to.meta.title = to.params.project_name_slug;
next();
},
beforeRouteUpdate(to, from, next) {
to.meta.title = to.params.project_name_slug;
next();
}
}
您可以像使用静态元一样使用 afterEach
,因为它已经设置好了:
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
// document.title = to.meta.title || DEFAULT_TITLE;
document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});
(注意: 在路由定义中使用 beforeEnter
是不够的,因为它不会在从一个动态参数转到另一个动态参数时触发。甚至 <router-view :key="$route.fullPath"></router-view>
更改参数时不会触发 beforeEnter
。)
我假设您是在询问如何在初始化组件之前执行此操作,因为您有 SEO 问题,否则它就像从 axios 请求中的 JSON 响应中提取它并使用一样简单document.title = myJson.page_title
在组件内。
如果您的最终目标是消除因对 SEO 的担忧(这完全有效)而产生的恐惧,那么您需要改变方法,使 JSON 数据甚至在组件出现之前可用渲染。
我建议在你的路由导航守卫中发出 axios 请求,并提前 hydrating 路由 属性,这样你就可以实际访问页面标题。观察:
更新您的路线以接受新元属性:
meta: {
title: "project detail",
content: []
}
在包含导航卫士的文件中导入 axios
并执行 axios 请求以获取和水合 content
。从 afterEach
迁移到 beforeEach
,这样您就可以在收到数据之前阻止组件的呈现:
import axios from 'axios'
router.beforeEach(async(to, from, next) => {
const { response } = await axios.get(`/my/cms/endpoint/${to.params.project_name_slug}`)
document.title = `my blog - ${response.data.title}`
to.meta.content = response.data.content
next()
})
I made some assumptions about the shape of your response above, you'll need to modify that to fit your server response.
现在在您的组件中,您将能够访问 this.$route.meta.content
并且您可以在 mounted
生命周期中利用它来滋润本地 属性,或使用 getter 到 return 它,我假设你已经在做类似的事情了:
export default {
get pageContent () {
return this.$route.meta.content
}
}
这是旧的,但如果它对任何人有帮助,我刚遇到这个问题,我发现使用 router.afterEach 静态标题的组合与动态标题的 mixin 结合使用。
在 OP 解释的情况下,我将从路由器和 afterEach 中的任何动态页面中删除 title 道具,只需检查 meta.title
router.afterEach(to => {
if (to.meta.title) {
document.title = `${to.meta.title} - my blog`;
}
});
然后为其他页面创建一个简单的 mixin,例如:
export default {
methods: {
setTitle(str) {
document.title = `${str} - my blog`
}
}
}
然后在这些动态页面中,您只需使用从服务器加载的任何动态数据调用 this.setTitle()。我知道这看起来太简单了,但它确实有效。我在使用您在 SO 上找到的所有 beforeEach 方法时遇到了问题。
注意:这不适用于 SEO 或网络爬虫(为此我推荐 prerenderSpa),但确实会为您提供漂亮的标题、后退按钮历史记录和书签。
我有一个使用 Vue CLI 创建的简单 Vue-based 网站,我正在尝试弄清楚如何为带有动态路由的视图动态生成页面标题。该站点正在从无头 CMS 中提取 JSON 数据,并且我为“项目”内容类型的详细视图设置了动态路由。我将动态路由设置如下:
// single project vue (dynamic)
{
path: "/projects/:project_name_slug",
name: "single-project",
component: () =>
import(
/* webpackChunkName: "single-project" */ "./views/SingleProject.vue"
),
meta: {
title: "project detail",
}
}
我添加了以下内容,可用于添加静态页面标题:
// show page titles
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
// document.title = to.meta.title || DEFAULT_TITLE;
document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});
按照目前的情况,在访问项目详细信息视图时,标题将显示为“我的博客 - 项目详细信息”;但是,我希望它从 project_name
的 JSON/field 数据中提取实际项目名称(就像路由路径使用 project_name_slug
一样),但到目前为止我还没有尝试过已经工作了。例如,使用 meta: { title: (route) => route.params.project_name }
只会导致原始函数文本显示在“我的博客 - ”之后。因此,对于那些动态视图,我希望 to.meta.title
解析为项目名称,创建“我的博客 - {项目名称}”。感谢您在这里提供的任何帮助,如果我需要提供更多详细信息,请告诉我。
*注意:这个问题与
在路由器的beforeEach
导航守卫中设置meta
:
router.beforeEach((to, from, next) => {
to.meta.title = to.params.project_name_slug;
next();
});
-或-
您可以使用 beforeRouteEnter
和 beforeRouteUpdate
in-component guards:
export default {
...
beforeRouteEnter(to, from, next) {
to.meta.title = to.params.project_name_slug;
next();
},
beforeRouteUpdate(to, from, next) {
to.meta.title = to.params.project_name_slug;
next();
}
}
您可以像使用静态元一样使用 afterEach
,因为它已经设置好了:
const DEFAULT_TITLE = "my blog";
router.afterEach((to, from) => {
// document.title = to.meta.title || DEFAULT_TITLE;
document.title = "my blog - " + to.meta.title || DEFAULT_TITLE;
});
(注意: 在路由定义中使用 beforeEnter
是不够的,因为它不会在从一个动态参数转到另一个动态参数时触发。甚至 <router-view :key="$route.fullPath"></router-view>
更改参数时不会触发 beforeEnter
。)
我假设您是在询问如何在初始化组件之前执行此操作,因为您有 SEO 问题,否则它就像从 axios 请求中的 JSON 响应中提取它并使用一样简单document.title = myJson.page_title
在组件内。
如果您的最终目标是消除因对 SEO 的担忧(这完全有效)而产生的恐惧,那么您需要改变方法,使 JSON 数据甚至在组件出现之前可用渲染。
我建议在你的路由导航守卫中发出 axios 请求,并提前 hydrating 路由 属性,这样你就可以实际访问页面标题。观察:
更新您的路线以接受新元属性:
meta: {
title: "project detail",
content: []
}
在包含导航卫士的文件中导入 axios
并执行 axios 请求以获取和水合 content
。从 afterEach
迁移到 beforeEach
,这样您就可以在收到数据之前阻止组件的呈现:
import axios from 'axios'
router.beforeEach(async(to, from, next) => {
const { response } = await axios.get(`/my/cms/endpoint/${to.params.project_name_slug}`)
document.title = `my blog - ${response.data.title}`
to.meta.content = response.data.content
next()
})
I made some assumptions about the shape of your response above, you'll need to modify that to fit your server response.
现在在您的组件中,您将能够访问 this.$route.meta.content
并且您可以在 mounted
生命周期中利用它来滋润本地 属性,或使用 getter 到 return 它,我假设你已经在做类似的事情了:
export default {
get pageContent () {
return this.$route.meta.content
}
}
这是旧的,但如果它对任何人有帮助,我刚遇到这个问题,我发现使用 router.afterEach 静态标题的组合与动态标题的 mixin 结合使用。
在 OP 解释的情况下,我将从路由器和 afterEach 中的任何动态页面中删除 title 道具,只需检查 meta.title
router.afterEach(to => {
if (to.meta.title) {
document.title = `${to.meta.title} - my blog`;
}
});
然后为其他页面创建一个简单的 mixin,例如:
export default {
methods: {
setTitle(str) {
document.title = `${str} - my blog`
}
}
}
然后在这些动态页面中,您只需使用从服务器加载的任何动态数据调用 this.setTitle()。我知道这看起来太简单了,但它确实有效。我在使用您在 SO 上找到的所有 beforeEach 方法时遇到了问题。
注意:这不适用于 SEO 或网络爬虫(为此我推荐 prerenderSpa),但确实会为您提供漂亮的标题、后退按钮历史记录和书签。