# 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方法