附:「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
前言
基本概念
什么是路由(router)
- 路由就是对应关系
- Hash地址和组件之间的关系(Hash === # 锚链接,vue换了一个马甲)
- 如:www.baidu.com/#/2,这里的hash… #/2
前端路由工作方式
- 用户点击了页面上的路由链接
- 导致了 URL地址栏 中的 Hash值发生了变化
- 前端路由监听了到 Hash 地址的变化
- 前端路由把当前 Hash地址对应的组件 渲染到到浏览器中
小总结:点击路由链接,浏览器会渲染当前 Hash 地址对应的组件内容
常用操作
路由重定向(redirect)
当用户访问 A 页面的时候,强制用户跳转到 B页面。从而展示特定的组件页面,这个就是路由重定向。
- 在路由规则里(routes)使用 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向
小总结:当我访问 http://localhost:8080/,自动跳转至首页页面
嵌套路由
嵌套路由
(1)About组件
// About组件
<template>
<div>
<h2>About组件</h2>
<!-- 子级路由链接 -->
<router-link to="/about/tab1">tab1</router-link>
<router-link to="/about/tab2">tab2</router-link>
<hr/>
<!-- 子级路由占位符 -->
<router-view></router-view>
</div>
</template>
(2)配置子路由规则
// router/index.js
<script>
import Tab1 from "@/components/tabs/Tab1.vue"
import Tab2 from "@/components/tabs/Tab2.vue"
const router = new VueRouter({
routes:[
{ // about (父级路由规则)
path:"/about",
component:About,
children: [ // 1. 通过children属性,嵌套声明子级路由规则
{path:"tab1",component:Tab1},
{path:"tab2",component:Tab2},
]
}
]
})
</script>
注意:children子路由规则的路径,前面不要加 /
默认子路由
如果 children 数组中,某个路由规则的 path 值为空字符串,则这条路由规则,叫做默认子路由
(1)接嵌套路由这个例子,当我访问about页面的时候,还需要手动点击子级路由 tab1 才会展示对应的内容,此时如果你想点击 about 后展示 tab1的内容,就可以在 children 中 把对应组件的path 改为空字符串,这样就可以实现访问 about 页面的时候,默认显示子级路由的类型
// router/index.js
<script>
import Tab1 from "@/components/tabs/Tab1.vue"
import Tab2 from "@/components/tabs/Tab2.vue"
const router = new VueRouter({
routes:[
{
path:"/about",
component:About,
children: [
{path:"",component:Tab1},
{path:"tab2",component:Tab2},
]
}
]
})
</script>
使用默认子路由要注意把 跳转链接 的地址修改一下
- 从原来的 /about/tab1 改为 /about
- 这样的话,当访问 about组件 会自动的显示 tab1的内容
<router-link to="/about">tab1</router-link>
<router-link to="/about/tab2">tab2</router-link>
(2)也可以使用重定向的方式
// router/index.js
<script>
import Tab1 from "@/components/tabs/Tab1.vue"
import Tab2 from "@/components/tabs/Tab2.vue"
const router = new VueRouter({
routes:[
{
path:"/about",
component:About,
redirect:"/about/tab1",
children: [
{path:"tab1",component:Tab1},
{path:"tab2",component:Tab2},
]
}
]
})
</script>
动态路由
定义参数项
把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性
- 使用英文的冒号( : )来定义路由的参数项
- 后面的名字是自定义,不过通常使用 id
获取路由对象参数
(1)this.$route.params.id
- 获取路径参数
- 假设有/about/1
- 它能获取的就是1
(2)props【推荐方式】
- 组件中使用 props 接收参数
- 路由规则中开启 props: true
- 假设有/about/1
- 它能获取的就是1
\
(3)$route.query
- 获取 ?后面的参数(也叫查询参数)
- 如:/about/1/?name=xiaohe age=18
(4)$route.fullpath
- 获取到完整的路径,包含查询参数
(5)path
- 获取不带查询参数的路径
这一些都是在当前组件实例的对象上,我们可以打印 this 慢慢调试
声明式导航 & 编程式导航
声明式导航
在浏览中,点击链接实现导航的方式,叫做声明式导航。
例如:
- 普通网页中的 链接
- vue项目中点击 都属于声明式导航
<router-link to="/about"></router-link>
编程式导航
在浏览器中,调用API方法实现导航的方式,叫做编程式导航。
例如:
- 普通网页中调用 location.href 跳转到新页面的方式,属于编程式导航
接下来说一下 vue中的编程导航
- this.$router.push("hash地址")
- 参数:hash地址 ,如:/about/1
- push 会增加一条历史记录(浏览器的左上方箭头可前进可后退)
- this.$router.replace("hash地址")
- 参数:hash地址 ,如:/about/1
- replace 不会增加一条历史记录(浏览器的左上方箭头不可前进和后退)
- this.$router.go(数值)
- 参数:任意 -1 ,1 数字
- 在浏览历史中前进和后退,如果是1,那么前进1次,如果是-2,后退2步
- router.back()
- 这两种是项目中最常用的方式,因为我们一般只用前进一层或者后退一层
- forward() 前进到下一个页面
- back() 后退到上一个页面
示例:
小总结:router.back() 是最常用的 API,前进和后退
导航守卫
概念
导航守卫是控制路由的访问权限的
主要的解决问题是:用户未登录的情况下是不能访问到登陆后的页面的
图示:
全局前置守卫
只要项目中发生了路由的跳转就必然会触发全局前置守卫(beforeEach),因此,在全局前置守卫中,程序员可以对每个路由进行 访问权限 的控制
- 全局前置守卫的回调函数中接收3个形参
router.beforeEach((to,from.next)=>{
})
- to:表示将要访问的路由对象
- from:将要离开的路由对象
- next:是一个函数,调用 next() 表示放行,允许这次路由导航
我们在全局 router/index 声明了 beforeEach , 如果不调用 next() ,哪里都去不了,因为只要跳转就会触发这个全局前置守卫
next函数的3种调用方式
- 当前用户拥有后台主页的访问权限,直接放行:next()
- 当前用户没有后台主页的访问权限,强制其跳转到登录页面:next("/login")
- 当前用户没有后台主页的访问权限,不允许跳转到后台主页(原地不动):next(false)
图示:
登录案例分析
分析
- 要拿到用户将要访问的 hash 地址
- 判断 hash 地址是否等于 /main
- 如果等于 /main ,证明需要登录之后,才能访问成功
- 如果不等于 /main,则不需要登录,直接放行 next()
- 如果访问的地址是 /main,则需要读取 localStorage 中的 token 值是否存在
- 如果有 token ,则放行
- 如果没有 token,则强制跳转到 /login 登录页
代码
总结
route 和 router
- $route 是路由的参数对象(获取一些路由参数)
- $router 是路由的导航对象(实现跳转等相关功能)