【发布时间】:2017-03-04 15:11:48
【问题描述】:
我正在使用 vue.js v1.0、vue-router v0.7 和 WebPack 构建一个 Web 应用程序。我遵循Single File Component 模式,每个页面都有不同的组件。
我不知道在浏览 Web 应用程序页面时如何更改不同路由(或者可能是不同组件)中的页面标题。我还希望页面标题在浏览器历史记录中可用。
【问题讨论】:
标签: javascript vue.js vue-router
我正在使用 vue.js v1.0、vue-router v0.7 和 WebPack 构建一个 Web 应用程序。我遵循Single File Component 模式,每个页面都有不同的组件。
我不知道在浏览 Web 应用程序页面时如何更改不同路由(或者可能是不同组件)中的页面标题。我还希望页面标题在浏览器历史记录中可用。
【问题讨论】:
标签: javascript vue.js vue-router
除了我之前在此处发布的解决方案之外,我在经过一番研究后发现了第二种方法:使用Navigation Guards
正如我之前的回答中所详述的,问题出在:vue-router 第一次创建后可能会开始重用路由组件。确实没有必要在路由退出时销毁这些组件,并在后续路由进入时重新创建。因此,我之前的解决方案中的 created 挂钩可能不会在后续访问同一条路线时触发。因此,我们的窗口标题可能无法按预期工作。
为了解决这个问题,我们可以在 路由更改事件 上设置窗口标题。路由器实例有一个afterEach 钩子,它在路由更改后被调用。这可用于设置窗口标题,详情如下:
// Let's say this is your router instance, with all "Named Routes"
const ROUTER_INSTANCE = new VueRouter({
mode: "history",
routes: [
{ path: "/", name: "HomeComponentName", component: HomeComponent },
{ path: "/about", name: "AboutComponentName", component: AboutComponent },
{ path: "*", name: "RouteErrorName", component: RouteError }
]
})
// Assign page titles for each of the "named routes"
// Reason: This allows us to have short named routes, with descriptive title
const PAGE_TITLE = {
"HomeComponentName": "Your Dashboard",
"AboutComponentName": "About Us Page",
"RouteErrorName": "Error: Page not found"
}
ROUTER_INSTANCE.afterEach((toRoute, fromRoute) => {
window.document.title = PAGE_TITLE[toRoute.name]
console.log(toRoute) // this lets you check what else is available to you here
})
如果您在类似的路线之间导航,例如“/user/foo”到“/user/bar”,这可能仍然对您没有帮助。如果您想要标题栏中的用户名或某些动态页面特定信息,请查看 Reacting to Params Changes,详细信息请参见 http://router.vuejs.org/en/essentials/dynamic-matching.html。根据文档,我们应该可以在组件中使用watch,如下所示:
watch: {
'$route' (toRoute, fromRoute) {
window.document.title = "some page title"
}
}
希望对你有帮助!
【讨论】:
afterEach 放在根Vue 组件的mounted() 函数中。随着页面列表的增长,将其提取到其他地方可能是值得的。 (TBH:我完全忘记了你可以通过 JS 设置窗口标题!)
前几天我也遇到了同样的问题,在我的路由组件定义中解决如下:
export default {
created: function() {
window.document.title = "Page Title for this route"
...
},
...
}
这确实不是正确的做法。原因:我做了一个很大的假设,即每次更改为新路由时都会创建 路由组件。 vue-router 目前是这样,但将来可能会改变。
我之前在 Angular 1.4 中使用ui-router,它允许 路由组件 存在于内存中(粘性状态),以便下次路由更改是即时的。如果 vue-router 曾经实现类似于 sticky states 的东西,我上面在 created 挂钩中设置标题的方法将失败。
但在此之前,您可以使用此解决方案。
【讨论】:
<router-view></router-view> 内部呈现的组件。如果我们在其挂载的钩子中更改窗口标题,它将第一次工作。但是后来当旧的组件实例被重用时,挂载的钩子可能不会运行,因此窗口标题不会更新。
我有一个解决方案,并在我的projects 上使用了它。
首先创建一个指令。
Vue.directive('title', {
inserted: (el, binding) => document.title = binding.value,
update: (el, binding) => document.title = binding.value
})
假设,我们正在处理'MyComponent.vue' 文件。
然后在router-view 组件上使用该指令。
<router-view v-title="title" ></router-view>
export default {
data(){
return {
title: 'This will be the title'
}
}
}
即使组件已更新或页面已重新加载,此功能也有效。
对我来说效果很好!!
【讨论】:
router-view 的地方定义。对于其他路线,这不会改变。