一、序言
对于一般性的前后端分离部署下的Vue项目而言,Vue Router可以说是必不可少的工具。最基本的情况下,我们在工程中使用Vue Router实现前端路由的路由注册、管理、跳转等功能。但Vue Router提供的功能绝不仅限于此,合理巧妙地使用Vue Router能够在很多情况下方便开发及实现一些特殊效果。
二、路由守卫
2.1 全局路由守卫
Vue Router的一个常用配置就是路由守卫,通过router.beforeEach可以在每一次路由跳转之前进行权限判断或其他针对路由跳转的逻辑处理。以如下代码为例(个人在工程中的通常配置):
router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} | XX后台管理系统`;
const role = localStorage.getItem('username');
if (!role && to.path !== '/login') {
next('/login');
} else if (to.meta.permission) {
// 如果是管理员权限则可进入
role === 'admin' ? next() : next('/403');
}
});
可以看到,在路由跳转之前,分别对用户信息、用户权限进行判断,如果不符合条件,则直接进行指定页面的跳转,这就是路由守卫的典型用法。
2.2 组件内路由守卫
组件内定义路由守卫包括以下三个钩子函数:
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
官方文档说明如下:
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
三、路由跳转事件
与路由跳转相关的事件一般作为钩子函数,在对应的触发节点进行相应的函数处理。这里我分为三个点对用法进行举例说明
3.1 重定向
重定向是指路由的替换,如对/a进行重定向设置为/b,则访问/a会直接跳转到/b,同时注意路由守卫对/a不起作用,只对跳转目标路由起作用。
但重定向不仅仅是以上的官方文档说明,在工程中,我们可以使用重定向对未登录下的页面访问进行登录重定向,然后方可跳转至访问页面,代码如下:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
3.2 路由监听
对于组件来说,可以使用watch监听$route的变化,并由此在$route变化时进行钩子函数的事件触发。以官方文档的示例为例:
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// 组件创建完后获取数据,
// 此时 data 已经被 observed 了
this.fetchData()
},
watch: {
// 如果路由有变化,会再次执行该方法
'$route': 'fetchData'
//$route(to, from) {
// 也可以以此形式对路由变化作出响应...
//}
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
// replace getPost with your data fetching util / API wrapper
getPost(this.$route.params.id, (err, post) => {
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
通过对$route进行监听,可以做到在路由变化时完成数据的更新。
同样的,也可以通过组件内的路由变化钩子函数进行对应的函数触发:
//通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改变前,组件就已经渲染完了
// 逻辑稍稍不同
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
3.3 动态过渡
在Vue Router中,可以使用<transition>包裹<router-view>,从而为路由跳转提供动态过渡效果:
<!-- 使用动态的 transition name -->
<transition :name="transitionName">
<router-view></router-view>
</transition>
// 接着在父组件内
// watch $route 决定使用哪种过渡
watch: {
'$route' (to, from) {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}
四、补充
以上所提及的Vue Router用法尚不够全面,而且基于以上的用法还可以制作更为精巧的效果(如页面动态标签及与Element UI的导航组件的联动配置),Vue Router其余的如模式(hash,history),路由元信息,懒加载等可自行参阅相关文档或使用说明。