Vue-Router
参数或者查询的改变并不会触发进入/离开的导航守卫,可以通过观察$route对象来应对这些变化,或者使用beforRoute的组件内守卫
全局前置守卫 router.beforeEach
注册全局前置守卫
cosnt router = new VueRouter({...})
router.beforeEach((to,from,next)=>{
//...
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行的,此时导航在所有守卫resolve完之前一直处于等待中
全局解析守卫 router.beforeResolve
在2.5.0+你可以用router.beforeResolve注册一个全局守卫。这个和router.beforeEach类似,区别是在导航被确之前,同时在所有的组件内守卫和异步路由组件被解析之后,解析守卫就被调用了。
全局后置钩子router.afterEach
全局后置钩子,和守卫不同的是,这些钩子不会接受next函数,也不会改变导航本身
router.afterEac((to,from)=>{
//...
})
路由独享的守卫beforeEnter
const router = new VueRouter({
routes:[
{
path:'/foo',
component:Foo,
beforeEnter:(to,from,next){
//...
}
}
]
})
组件内的守卫
组件内的守卫可以直接在路由组件内直接定义
组件内的守卫: beforeRouteEnter /beforeRouteUpdate /beforeRouteLeave
const Foo = {
template:'...',
beforeRouteEnter(to,from,next){
//在渲染该组件的对应路由被confirm前调用
//不!能!获取组件实例的`this`
//因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to,from,next){
//在当前路由改变,但是该组件本地被复用是调用
//举例来说,对于一个带有动态参数的路径/foo/:id,在/foo1和foo2之间跳转的时候
//由于会渲染同样的Foo组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
//可以访问组件实例的`this`
},
beforeRouteLeave(to,from,next){
//导航离开该组件的对应路由时吊我们会
//可以访问组件实例的`this`
}
}
beforeRouteEnter守卫不能访问this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建
不过,可以通过传一个回调函数给next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回到方法的参数
beforeRouteEnter(to,from,next){
next(vm=>{
//通过`vm`访问组件实例
})
}
注意beforeRouteEnter是支持给next传递回调的唯一守卫。对于beforeRouteUpdate和beforeRouteLeave来说,this已经可用了,所以不支持传递回调,因为没有必要
beforeRouteUpdate(to,from,next)=>{
this.name = to.params.name
next()
}
beforeRouteLeave这个离开守卫通常用来禁止用户还未保存修改的前突然离开。该导航可以通过next(false)来取消
beforeRouteLeave(to,from,next){
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if(answer){
next()
}else{
next(false)
}
}
完整的导航解析流程
- 导航被触发
- 在失活的组件里调用beforeRouteLeave守卫
- 调用全局的beforeEach守卫
- 在重用的组件里调用beforeRouteUpdate守卫
- 在路由配置里调用beforeEnter
- 解析异步路由组件
- 在被激活的组件里调用beforeRouteEnter
- 调用全局的beforeResolve守卫
- 导航被确认
- 调用全局的afterEach钩子
- 触发DOM渲染
- 调用beforeRouteEnter守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入
总结
全局导航 :
前置守卫:router.beforeEach ========>>> 权限的控制
解析守卫:router.beforeResolve
后置守卫: router.afterEach
路由独享 :beforeEnter
组件内守卫:
beforeRouteEnter
beforeRouteUpadte
beforeRouteLeave
history 模式下不同页面跳转传参
使用router 的name属性
也就是params来传递参数
//跳转到Message页面 传参
this.$router.push({
name:"Message"
params:{
userId:'1101'
}
})
//在Message页面取参数
this.$route.params.userId
使用query来传递参数
//跳转到login页面 传参
this.$router.push({
path:'/login',
query:{
userId:'1101'
}
})
//在login页面取参
this.$route.query.useId
总结
params 传参必须要有name属性
query 传参必须要有path属性
params类似于ajax中post传参,不会在url中展示参数,但是query则类似get传参,会在url中展示参数
query传参,刷新页面不会丢失参数。但是params会丢参的。
params 和path不能共存 所以只能用name
params传参 需要在 路由配置 path /:id 这样就不会丢参
最重要的一点,params刷新会消失。。。query则不会,params参数只要在路由中声明了就不会消失。
在路由声明了,跟query又有什么区别呢,干嘛不直接query呢,params不会出现在地址栏,更加美观。
路由声明path里加上参数(冒号加参数名称)比如 /article/:articleId/:articleType 这样你通过params传递的articleId和articleType就会在路由路径里。
$router是路由对象,是一个只写的对象
$route是当前路由的信息对象,是一个只读的对象
hash模式与history模式的区别
在本地开发的时候,其实两种模式对开发影响不大,主要是在项目部署上线的时候,影响较大。
history 模式下:将url地址输入到浏览器的时候或者刷新页面的时候,此时的url相当于发送了一次get请求,这个请求,后台可能会找不到资源的,所以会404。
但是hash 模式下,不会带着#后面的参数,所以不会有什么问题(hash值不会包含在HTTP请求中,即hash值不会带给服务器)。
-
hash模式:
-
hash模式是通过改变锚点(#)来更新页面URL,并不会触发页面重新加载,我们可以通过window.onhashchange监听到hash的改变,从而处理路由。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面
-
地址中永远带着#号,不美观
-
兼容性较好(能兼容到IE8)
-
-
history 模式
-
history模式是通过调用window.history对象上的一系列方法来实现页面的无刷新跳转。
-
地址干净美观
-
兼容性与hash模式相比略差(能兼容到IE10)
-
应用部署上线时,需要后端支持,解决刷新页面服务端404的问题
-