# VUE-Router 🎃
# mode中history和hash的区别
hash
—— 即地址栏URL
中的 # 符号(此hash
不是密码学里的散列运算)。 比如这个URL
:http://www.abc.com/#/hello
,hash
的值为#/hello
。它的特点在于:hash
虽然出现在URL
中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变hash
不会重新加载页面。history
—— 利用了 HTML5 History Interface 中新增的pushState()
和replaceState()
方法。(需要特定浏览器支持) 这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的URL
,但浏览器不会立即向后端发送请求。
# history的优势
pushState()
设置的新URL
可以是与当前URL
同源的任意URL
;而hash
只可修改 # 后面的部分,因此只能设置与当前URL
同文档的URL
;pushState()
设置的新URL
可以与当前URL
一模一样,这样也会把记录添加到栈中;而hash
设置的新值必须与原来不一样才会触发动作将记录添加到栈中;pushState()
通过stateObject
参数可以添加任意类型的数据到记录中;而hash
只可添加短字符串;pushState()
可额外设置title
属性供后续使用。
# history的缺点
history
—— SPA
虽然在浏览器里游刃有余,但真要通过 URL
向后端发起 HTTP
请求时,两者的差异就来了。尤其在用户手动输入 URL
后回车,或者刷新(重启)浏览器的时候。
hash
模式下,仅hash
符号之前的内容会被包含在请求中,如http://www.abc.com
,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。history
模式下,前端的URL
必须和实际向后端发起请求的URL
一致,如http://www.abc.com/book/id
。如果后端缺少对/book/id
的路由处理,将返回 404 错误。
# 全局守卫
# 全局前置守卫
使用router.beforeEach
注册一个全局前置守卫,要在做页面的权限控制就可以将判断写在这里。
router.beforeEach((to, from, next) => {
// ...
})
1
2
3
2
3
router.beforeEach
中的参数:
- to:进入到哪个路由去;
- from:从哪个路由离开;
- next:函数,决定展示页面的路由。
const token = window.localStorage.getItem('accessToken')
router.beforeEach((to, from, next) => {
if (token) {
next({
path: '/'
});
} else {
alert('您还没有登录,请先登录');
next({
path: '/login'
});
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 登录成功后将token存在本地,这里先在本地取token,如果有token则说明登录成功,直接跳到首页,如果没有登录成功则页面跳转至登录页。
# 全局解析守卫
# 全局后置钩子
使用router.afterEach
注册一个全局后置钩子
router.afterEach((to, from) => {
// ...
})
1
2
3
2
3
router.afterEach
中的参数:
- to:进入到哪个路由去;
- from:从哪个路由离开。
router.afterEach((to, from) => {
alert("展示页面")
})
1
2
3
2
3
- 每次切换路由时,都会弹出alert,点击确定后,才会展示当前页面。
- 切换路由时,路由切换到需要跳转的路由,但是页面不会加载,确定弹出框后,页面才会开始加载。
# 路由独享守卫
在路由配置上直接定义beforeEnter
守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 这些守卫与全局前置守卫的方法参数是一样的。
# 组件内的守卫
# 完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发
DOM
更新。 - 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
# 路由跳转
在遇到系统对接时,需要单独用一个页面处理逻辑,做为中转页面时,我们可以将push
更换为replace
1.push方法:
- router.push()方法会将新的路由添加到历史记录中,同时会导航到该路由页面。
- 新的路由会被添加到浏览器的历史记录栈中,因此用户可以使用浏览器的回退按钮返回上一个路由。
- 使用push进行路由跳转时,会增加新的历史记录条目,每个跳转都会创建一个新的历史记录
2.replace方法:
- router.replace()方法会替换当前的路由记录,而不会添加新的历史记录。
- 替换当前路由记录后,用户不能通过浏览器的回退按钮返回到前一个路由。
- 使用replace进行路由跳转时,不会增加新的历史记录条目
总结:根据具体的需求,选择适合的方法。如果希望用户可以通过浏览器的回退按钮返回上一个路由,则使用push方法。如果希望跳转后不产生新的历史记录,或者希望替换当前的路由记录,则使用replace方法