配置Vue路由
# 配置 Vue 路由
1. 先定义一个新的页面 如 src/views/login/index.vue
<template>
<div class="login-container">
<h2>登陆页面</h2>
</div>
</template>
<script>
export default {
name: 'LoginIndex',
data () {
return {
num: 1
}
}
}
</script>
<style lang="less"></style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2. 在 router 的 index.js 中 引用 并配置
import Login from '@/views/login' //引用页面文件
//@ 在vue cli中表示src中的文件 注意要@后面加斜杠
//在routes数组中添加路由器地址 名字 元件
const routes = [{
path: '/login',
name: 'login',
component: Login
}
]
const router = new VueRouter({
routes
})
// 我们在组件中使用的this.$router其实就是导出的router模块
export default router
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 最后手动输入
/login访问测试。
# 控制页面访问权限
在我们的项目中,除了登录页面,其它所有页面都需要具有登录状态才能访问。也就是说我们要给这些需要登录才能访问的页面进行统一控制。
通常的做法就是利用路由的导航守卫来统一处理。
所谓的路由拦截器就是一个公共的页面访问门卫,说白了就是所有的页面访问都要经过这里,我们可以在这里执行一共公共的操作,例如校验是否具有登录状态。
提示:官方文档叫导航守卫,都是一个意思。
具体做法就是在 src/router/index.js 中:
// 路由导航守卫:说白了所有页面的导航都会经过这里
// 守卫页面的导航的
// to:要去的路由信息
// from:来自哪里的路由信息
// next:放行方法
router.beforeEach((to, from, next) => {
// 如果要访问的页面不是 /login,校验登录状态
// 如果没有登录,则跳转到登录页面
// 如果登录了,则允许通过
// 允许通过
// next()
const user = JSON.parse(window.localStorage.getItem('user'))
// 校验非登录页面的登录状态
if (to.path !== '/login') {
if (user) {
// 已登录,允许通过
next()
} else {
// 没有登录,跳转到登录页面
next('/login')
}
} else {
// 登录页面,正常允许通过
next()
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
关于路由导航守卫更详细的用户请参考官方文档:[https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
# 结合导航守卫实现页面切换顶部进度条
路由前置钩子
路由后置钩子

1、安装 nprogress
# yarn add nprogress
npm i nprogress
2
注意:项目中不要乱用包管理工具,要从一而终,不要一会儿这个,一会儿那个的。否则的话会导致一些包被莫名删除。
提示:如果想要从一个包管理工具切换到另一个包管理工具:
1、手动删除 node_modules
2、执行 npm install 或者 yarn install 或者 cnpm install 把所有依赖项重新安装一遍
3、之后固定使用 npm、yarn、cnpm 来装包
注意:cnpm 就不建议使用了。
2、在 main.js 中引入 nprogress.css 样式文件
// 加载 nprogress 中的指定的样式文件
// 注意:加载第三方包中的具体文件不需要写具体路径,直接写包名即可
// 总结就是:"包名/具体文件路径"
import "nprogress/nprogress.css";
2
3
4
3、在路由的全局前置守卫中,开启进度条
...
+ import NProgress from 'nprogress'
router.beforeEach((to, from, next) => {
// 开启顶部导航进度条特效
+ NProgress.start()
// 停止导航
// 我们可以在一些特殊情况下,停留在当前页面,中断当前导航
// next(false)
// next()
// 1. 如果访问的是登录页面,则直接放行
if (to.path === '/login') {
next()
// 停止代码往后执行
return
}
// 2. 非登录页面,校验登录状态
// 2.1 获取用户 token
const token = window.localStorage.getItem('user-token')
// 2.2 判断是否有 token,有就通过
if (token) {
// 导航通过,放行,访问哪里就往哪里走
next()
} else {
// 2.3 没有,就跳转到登录页
next('/login') // 跳转到指定路由
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
4、在路由的全局后置钩子中,关闭进度条特效
router.afterEach((to, from) => {
// 结束顶部的导航进度条
NProgress.done();
});
2
3
4
# 禁用路由缓存
我们发现一个小问题,从编辑文章导航到发布文章,表单内容并没有被清空,这是因为两个路由共用的同一个组件,两者之间相互跳转的时候,原来的组件实例会被复用。 因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
路由默认提供的这个功能的用意是好的,但是有时候却会带来问题,解决方案就是:禁用缓存。
方法 1 : 在路由出口 router-view 上添加一个唯一的 key 即可。
<router-view :key="$route.fullPath"/>
$route.fullPath
当路由地址变化为 /category/sub1 ==> /category/sub2 时
当路由地址变化为 /category/sub?id=1 ==> /category/sub?id=1 时
这两种情况由于这两个路由的 $route.fullPath 都不一样,所以组件被强制重新加载
相关钩子加载顺序为 : beforeRouteUpdate => created => mounted
还有个类似的值 $route.path
- 当路由地址变化为 /category/sub1 ==> /category/sub2 时
由于这两个路由的 $route.path 不一样,所以组件被强制重新加载
相关钩子加载顺序为 : beforeRouteUpdate => created => mounted
- 当路由地址变化为 /category/sub?id=1 ==> /category/sub?id=1 时
由于这两个路由的 $route.path 一样,所以组件被复用,不重新加载
相关钩子加载顺序为 : beforeRouteUpdate
方法 2 : 使用 watch 监听 (opens new window) id 变化重新拉取接口
// (对象|数组|函数, (newVal, oldVal) => {}, {immediate: true|false, deep:true|false })
watch(() => route.params.id, (newVal) => {
// 当id发生变化时重新发送Ajax并给数据复制
// ...代码
}, { immediate: true })
2
3
4
5
方法 3 : 使用 onBeforeRouteUpdate 钩子函数
// 只执行一次
onMounted(() => {
// 使用route.params.id发送ajax
})
// 路由变化时执行
// to:要跳转的路由对象
onBeforeRouteUpdate((to) => {
// 使用to.params.id发送ajax
})
2
3
4
5
6
7
8
9