$route和$router
$route是什么
前文提到过,再总结一下,$route
是当前活跃的路由对象。
$router是什么
$router
是创建出来的路由实例。
他们的由来
他们是vue-router给每个组件添加的两个属性。那vue-router是怎么实现这个功能的呢?
- 当Vue安装vue-router这个插件的时候(Vue.use(vue-router);),vue-router执行了它的install方法。
- install方法中,他给Vue这个类,或者说构造函数的原型对象上添加了两个属性:
$route
和$router
Vue.prototype.$route
=...;
Vue.prototype.$router
=根实例的options.Router(之前我们有把导出的路由实例,挂载到根实例上) - ** 所有的组件都会继承Vue的原型对象。所以导致所有的组件都会有这两个属性**
全局导航守卫
导航守卫其实可以完全理解成钩子函数。什么意思呢?当路由进行跳转的过程中,跳转前有个钩子,跳转后也有个钩子。就跟beforeCreate函数和created函数一样一样的。而全局导航守卫的意思就是任何路由跳转都会调用这个钩子函数。全局导航守卫是给生成的路由实例部署的。
前置守卫(前置钩子)
beforeEach函数,他是在路由跳转前回调的,它的参数就是一个函数
beforeEach((to,from,next)=>{});
解释一下这三个参数:
- to 要进入的路由对象。
- from 将要离开的路由对象。
- next 这是个方法,意思是跳转的意思。就是执行这个方法,路由就跳转了。所以当你复写beforeEach函数的时候,一定要记得调用next方法。不然路由无法跳转。(本身应该是实现了这个beforeEach函数,但是没有实际的内容只是执行了next方法,当你复写beforeEach函数,就会把本身的benforeEach函数覆盖,那么一定要记得再调用next方法。)
后置守卫(后置钩子)
afterEach函数,他是在路由跳转后回调的,他的参数也是函数。
afterEach((to,from)=>{});
- to 刚进入的路由对象
- from 刚离开的路由对象
它不用执行next方法,因为他已经跳转了。
结合导航守卫实现一个小需求
需求
目前,我们实现了三个分页,一个是home页,一个是about页,一个是listing-detail页。当它处于特定页面的时候,html的title应该显示对应的title
实现
router.beforeEach((to,from,next)=>
{
console.log(to);
document.title=to.meta.title;
next();
});
这里要用到一个路由对象的属性叫元数据。我们就把title的值存放在meta中。怎么存放在meta中呢?像params,query我们都是直接传递的,而meta是在配置路由对象的时候直接配置的: 实现效果: 可见有一个很明显的bug。就是开始时应该显示首页但是它显示的是undefined。原因是什么呢?肯定是to对应的那个路由对象有问题,它对应的home路由对象下面的子路由对象。 应该是它! 它并没有配置meta。我们得找它的父路由对象。怎么取得它的父路由对象呢?通过matched属性。match[0]就是它的父路由对象。就算路由对象是独立的,不存在路由嵌套。它的match[0]也是它本身。所以将代码优化一下
router.beforeEach((to,from,next)=>
{
console.log(to);
document.title=to.matched[0].meta.title;
next();
});
拓展:其他导航守卫
导航守卫分为三种:
- 全局导航守卫(已讲)
- 路由导航守卫
- 组件内导航守卫
路由导航守卫
见名知义,这是和路由紧密关联的。所以这个是部署在路由对象的内部的。形式是这样的: 路由导航守卫只有一个:beforeEnter,对应一个函数,也是这三个参数。它在进入该路由前被调用。
组件导航守卫
很显然,这应该和组件对应。应该是定义在组件内部。就很类似组件的生命周期函数。
- beforeRouteEnter,在该组件对应的路由被进入前,调用。
beforeRouteEnter(to,from,next)
{
}
- beforeRouteLeave,在该组件对应的路由被离开前,调用。
beforeRouteLeave(to,from,next)
{}
总结
beforeEach,beforeEnter,beforeRouteEnter都是在路由跳转前调用的。而afterEach是在路由离开后调用的,beforeRouteLeave是在路由即将离开的时候调用的。那他们之间的顺序究竟是怎么样的呢?(主要是前三个纠缠不清)
我们以/about
路由对象为例。
- 我添加了全局导航守卫,只要路由被跳转就被调用。
- 我添加了路由导航守卫,只要进入该路由就被调用
- 我添加了组件内导航守卫,只要该组件对应的路由进入或离开就被调用 那beforeEach,beforeEnter,beforeRouteEnter执行顺序会是怎么样呢?拭目以待。 我描述一下过程,当我们点击关于的时候:
- 路由从"/"跳转到'/about',发生路由的跳转。那么必然触发路由的全局守卫。beforeEach和afterEach。
- 对于'/about'路由对象来说,即将进入该路由,那么就会调用beforeEnter函数
- 对于about组件来说,即将进入与他对应的路由'/about',就会调用beforeRouteEnter函数。
从结果上来看,执行顺序应该是beforeEach->beforeEnter->beforeRouteEnter->路由跳转->afterEach
注意点
- 除afterEach外,**其他所有钩子函数都有next方法,一定要记得调用next方法才能进行下一步,不然路由的跳转就在此阻塞!!!!**我猜测应该是内部已经也有这些钩子,没有实际内容但是都执行了next方法,如果你复写,不执行next方法就进行不下去了。路由跳不动!
- 我发现一个问题,我刚进去的时候,也就是url:
localhost:8080
它也调用了beforeEach和afterEach方法,出于好奇我还对to/from进行了打印,发现他们的path都是空的:"/" - 第三个问题,当我们从"/about"->"/home"的时候,beforeRouteLeave执行顺序比beforeEach早
好了关于路由守卫的探讨就到这里了,有点儿绕,而且可能没有啥实际意义。。。。