一、路由的简介
1、实现生活中的路由
路由:路由其实就是一个key-value对应关系
路由器:用于管理多个路由关系的设备被称为路由器
2、前端的路由
目前使用的前端项目都是单页面的应用(SPA),一个项目中只有一个html页面,这种项目是由很多个组件组成,组件之间如果要跳转要依靠路由来完成,路由是由key和value组成一个对应关系,前端路由的key就是url地址,路由的value就是组件本身
key
value
http://localhost:8080/login
Login.vue
http://localhost:8080/register
Register.vue
总之:路由是实现多个组件之间进行跳转一种方式,使用路由将各组件之间联系起来
由于vue是一个渐进式的前端框架,vue的核心语法中不包括路由,路由以插件的形式存在,如果要去使用路由就要去将路由集成到vue项目中
二、路由的基本配置
1、路由的配置
由于路由不是vue的核心功能,大家如果要使用就需要去单独集成它,在vue中使用路由最多一个路由产品vue-router
vue-router的官网:Vue Router
注意:vue2的项目,匹配的路由版本是vue-router@3
配置的具体步骤如下
npm install [email protected]
//导入Vue包
import Vue from 'vue'
//导入VueRouter包
import VueRouter from 'vue-router'
//将VueRouter作为插件设置到Vue中
Vue.use(VueRouter)
//创建路由器对象
const router=new VueRouter()
//将这个路由器对象导出
export default router
import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')
2、一级路由的配置
路由是一个key-value的对应关系
//导入Vue包
import Vue from 'vue'
//导入VueRouter包
import VueRouter from 'vue-router'
//导入组件
import Login from '@/views/Login'
import Register from '@/views/Register'
import Home from '@/views/Home'
//将VueRouter作为插件设置到Vue中
Vue.use(VueRouter)
//创建routes数组
const routes=[
{
path:'/login',
component:Login
},
{
path:'/register',
component:Register
},
{
path:'/home',
component:Home
}
]
/*
创建路由器对象
const router=new VueRouter(config)
config:路由的配置对象
routes:路由配置的数组
*/
const router=new VueRouter({
routes
})
//将这个路由器对象导出
export default router
3、路由的出口设置
如上已经将路由的规则配置成功了,如果要显示在页面上,就需要配置路由出口
在App.vue根组件中配置路由出口
4、路由的跳转
使用vue-router进行路由跳转有两种方式
4.1、标签式路由跳转的案例
已有账号?前往登录
4.2、编程式路由跳转
npm i axios
"scripts": {
"serve": "vue-cli-service serve",
"serve:production": "set NODE_ENV=production&vue-cli-service serve",
"build": "vue-cli-service build"
}
const tokenkey="admin-token"
// 保存token到localStorage中的方法
export const setToken=tokenval=>localStorage.setItem(tokenkey,tokenval)
// 从localStorage中获取token
export const getToken=()=>localStorage.getToken(tokenkey)
位置:src/api/request.js
import axios from 'axios'
import {getToken} from '@/utils/auth'
/*
基础路由的配置
*/
switch(process.env.NODE_ENV){
case 'production':
axios.defaults.baseURL="http://47.98.128.191:3000/"
break;
default:
axios.defaults.baseURL="http://www.zhaijizhe.cn:3005"
break
}
/*
设置请求拦截器
*/
axios.interceptors.request.use(config=>{
//获取token的信息,然后将token信息携带到请求头信息中
if(getToken){
config.headers.Authorization=getToken()
}
return config
})
/*
设置响应拦截器
*/
axios.interceptors.response.use(response=>{
return response.data
},err=>{
if(err.response){
switch(err.response.status){
case 401:
break
case 404:
break
case 500:
break
}
}
})
export default axios
位置:src/api/modules/users.js
import request from '@/api/request'
export default{
login:(data)=>request.post('/users/login',data)
}
位置:src/api/api.js
import users from "./modules/users";
export default{
users
}
位置:src/main.js
import api from '@/api/api'
Vue.prototype.$api=api
位置:src/views/Login.vue
5、路由的嵌套
位置:src/router/index.js
{
path:'/home',
component:Home,
children:[
{
path:'workplace',//二级路由的path的前不要带/
component:workplace
},
{
path:'analysis',
component:analysis
},
{
path:'studentList',
component:studentList
}
]
}
位置:src/views/Home.vue
三、路由的其他配置
1、路由的重定向
所谓的路由重定向就是指当你输入一个路由的路径时候,它会自动重新跳转到另外一个路由上这种行为称为路由重定向
{
path:'/',
redirect:'/home'
},
2、路由懒加载
为了提高首屏加载速度,可以采用路由懒加载的方式,提升加载性能,避免白屏现象出现
//导入Vue包
import Vue from 'vue'
//导入VueRouter包
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//创建routes数组
const routes=[
{
path:'/login',
component:()=>import('@/views/Login')
},
{
path:'/register',
component:()=>import('@/views/Register')
},
{
path:'/',
redirect:'/home'
},
{
path:'/home',
component:()=>import('@/views/Home'),
children:[
{
path:'workplace',//二级路由的path的前不要带/
component:()=>import('@/views/dashboard/workplace.vue')
},
{
path:'analysis',
component:()=>import('@/views/dashboard/analysis.vue')
},
{
path:'studentList',
component:()=>import('@/views/students/studentList.vue')
}
]
}
]
const router=new VueRouter({
routes
})
//将这个路由器对象导出
export default router
3、缓存路由
export default {
name:'analysis'
}
exclude
:该组件不被缓存
include
:该组件会被缓存
4、路由的元信息
路由对象有很多属性,核心有两个,一个就是path,表示的路由的路径,component表示的是路由的对应的组件,除此之外还有其他的属性,比如meta属性,可以设置路由的额外信息,这里以两个例子给大家讲解
4.1、面包屑的功能
{
path:'workplace',//二级路由的path的前不要带/
component:()=>import('@/views/dashboard/workplace.vue'),
meta:{
firstTitle:'控制面板',
secondTitle:'工作台'
}
},
在src/components目录下创建BreadCrumb组件
{{$route.meta.firstTitle}} >{{$route.meta.secondTitle}}
学生列表
4.2、路由缓存状态设置
{
path:'workplace',//二级路由的path的前不要带/
component:()=>import('@/views/dashboard/workplace.vue'),
meta:{
firstTitle:'控制面板',
secondTitle:'工作台',
iskeepAlive:true
}
},
说明:这种设置方式较之前使用include或者exclude方式的更加合理。
四、路由传参
1、学生列表
import request from '@/api/request'
export default{
getStudents:params=>request.get('/students/getStudents',{params})
}
import users from "./modules/users";
import students from "./modules/students";
export default{
users,students
}
2、query传参
vue-router这个路由操作中,要进行传参有多种方式,比较常用的方式有两种
query传参的步骤
第1步:创建页面组件,配置路由
{
path:'studentDetail',
component:()=>import('@/views/students/studentDetail.vue'),
meta:{
firstTitle:'学生管理',
secondTitle:'学生详情'
}
}
第2步:进行传参
查看
查看
查看
//命名路由
查看
最后一种写法是使用了命名路由的写法,命名路由的好处就是使用name来指定要跳转位置
goStudentDetail(_id){
this.$router.push(`/home/studentDetail?_id=${_id}`)
}
goStudentDetail(_id){
this.$router.push('/home/studentDetail?_id='+_id)
}
goStudentDetail(_id){
this.$router.push({
path:'/home/studentDetail',
query:{
_id
}
})
}
goStudentDetail(_id){
this.$router.push({
name:'xsxq',
query:{
_id
}
})
}
第3步:接收路由参数
使用this.$route.query方式获取参数
export default {
components:{BreadCrumb},
created(){
console.log(this.$route.query._id);
}
}
$router和$route
面试题(简单的面试题)
4、params传参
动态路由概念:所谓的动态路由是指路由地址的一部分是变化的,像这种我们将其称为动态路由
http://localhost:8080/#/home/studentUpadate/10001
http://localhost:8080/#/home/studentUpadate/10002
http://localhost:8080/#/home/studentUpadate/10003
如上操作,如果有多条信息,就需要在router/index.js中配置多个路由信息对象,这种做法不可取,原因有两个
为了解决这个问题,我们可以动态路由的方式进行配置,具体配置步骤如下
第1步:在路由配置文件中配置如下
{
path:'studentUpdate/:id',
component:()=>import('@/views/students/studentUpdate.vue'),
meta:{
firstTitle:'学生管理',
secondTitle:'修改学生'
}
}
第2步:路由跳转传参
根据跳转方式的不同
修改
修改
this.$router.push('/home/studentUpdate/'+_id)
this.$router.push(`/home/studentUpdate/${_id}`)
goStudentUpdate(_id){
this.$router.push({
name:'xsxg',
params:{
id:_id
}
})
}
注意:如果要使用push方法的参数是配置对象形式参数,这种params只能和命名路由结合使用,不能和path一起使用
第3步:接收params参数
接收params参数有两个方法
console.log(this.$route.params.id);
配置步骤
首先:在路由对象设置可以使用props方式接收
{
name:'xsxg',
path:'studentUpdate/:id',
component:()=>import('@/views/students/studentUpdate.vue'),
meta:{
firstTitle:'学生管理',
secondTitle:'修改学生'
},
props:true
}
其次:在接收参数的组件中设置props选项
export default {
props:['id'],
}
最后,在组件中使用
export default {
props:['id'],
components:{
BreadCrumb
},
created(){
// console.log(this.$route.params.id);
console.log('id:',this.id);
}
}
5、修改学生
返回
刷新
五、路由模式【面试题】
由于Vue项目为单页面应用,所以整个项目在开发和构建过程中,仅存在一个HTML物理文件,通过路由系统可以实现将项目的组件与可访问的URL路径进行绑定。由于Vue项目只有一个HTML物理文件,切换页面时既需要让访问的URL路径发生变化,又不能触发HTML物理文件的重新加载,这就使得VueRouter的跳转模式不能使用普通的超链接方式。
VueRouter为了支持单页面应用的页面管理和页面跳转,提供了两种页面跳转和加载模式:
1、hash模式
hash模式使用了锚点技术重写URL访问路径,会在原有的URL路径后拼接/#/xx,这种方式可以在不重新加载原有HTML文件的基础上,实现切换URL路径的目的,hash模式的原理案例,代码如下
首页
关于我们
我是首页
我是关于页面
hash模式利用了纯静态技术,解决了单页面应用的页面划分,它可以在不触发网页重新加载的情况下切换URL路径,配合onhashchange可以实现,一旦URL中的hash部分发生变化,就触发函数通知,通过javascript编程便可以很快速的实现DOM对象的切换显示。
hash模式同时也存在着不足之处,如在分布式微前端项目中,嵌套的子应用和主应用都使用hash模式时,由于hash模式的URL路径只能存在一个#,会导致子应用和主应用在定义URL路径上存在着困难,hash模式的URL路径中包含#,也会在视觉上导致URL路径不美观
2、history模式
histroy模式是VueRouter中常用的一种路由模式,它与hash模式不同,不需要借助锚点技术重写URL路径,所以history模式使用的URL路径中不存在#,在视觉上更加美观,histroy模式采用histroy对象中的pushState()函数重写函数URL路径,可在触发重新加载的情况下变更URL路径,history的原理,代码如下
跳转到首页
跳转到about页
我是首页
我是关于页面
history模式重写URL路径的解决方案与hash模式现象类似,但本质不同,虽然histroy模式可以重写URL路径,但是重写后的新路径中并不包含原有HTML物理文件的访问路径,所以history模式在重写URL路径后,一旦刷新网页会造成404无法访问的效果,VueCli在开发环境中解决了history模式的刷新问题,不过项目发布到生产环境时,由于histroy模式的URL路径问题,还需要配合生产服务器的转发规则重写,用以支持history模式的路由加载。
可以在路由的配置文件中更改路由模式:
const router = new VueRouter({
routes: routes,
mode: 'history'
})
不设置 mode 属性,则默认为 hash 模式。
六、路由守卫
1、什么是路由守卫
当路由发生变化的时候,会触发的一些函数,我们这些函数中编写一定业务逻辑,这种函数称为路由守卫函数,也有人称为导航守卫
按照类型将导航守卫分为三大类
2、全局前置守卫
2.1、语法
router.beforeEach((to,from,next)=>{
})
参数说明:
案例:防止没有token直接进入后台
第1步:在router/index.js中编写路由全局前置守卫函数,完成token验证
router.beforeEach(async(to,from,next)=>{
console.log('********进入路由全局前置守卫************');
if(to.path=="/login"||to.path=="/register"){
console.log('即将要进入的是登录或者注册组件');
//放行进入
next()
}else{
//获取token
let token=getToken()
if(token){
let result=await api.users.getUserInfo()
if(result.code){
next()//放行进入
}
}else{
alert('您还没有登录,请先登录')
next('/login')
}
}
})
第2步:在二次封装axios的文件中request.js中补全401状态时的执行业务逻辑
axios.interceptors.response.use(response=>{
return response.data
},err=>{
if(err.response){
switch(err.response.status){
case 401:
console.log('进入到拦截器的401处理中');
//弹框提示
alert('您的token已失效,请重新登录')
//进行路由跳转
router.push('/login')
break
case 404:
break
case 500:
break
}
}
})
3、路由独享守卫
这种守卫函数,只针对于进入该路由所触发
{
path:'/home',
component:()=>import('@/views/Home'),
children:[
],
//如果进入该路由或者该路由下的子路由都会进入到这个守卫函数
beforeEnter:async function(to,from,next){
let token=getToken()
if(token){
let {code}=await Vue.prototype.$api.users.getUserInfo()
if(code){
next()
}
}else{
alert('您还没有登录,请登录')
next('/login')
}
}
}
4、组件内守卫
写在组件中
beforeRouteEnter:async function(to,from,next){
console.log('------进入该组件---------');
let result=await Vue.prototype.$api.users.getUserInfo()
if(result.data.auth==1){
console.log('------我是超级管理员-----------');
next()
}else if(result.data.auth==2){
console.log('-------我是普通管理员----------------------');
alert('您没有权限进入,请联系系统管理,为您开设权限')
}
// let result=await this.$api.users.getUserInfo()
// console.log('result',result);
},
beforeRouteLeave(to,from,next){
console.log('------离开该组件----------');
if(this.name==''||this.fcz==''||this.startTime==''){
if(window.confirm('您还没有输入完所有的信息,您确认你要离开吗?')){
next()
}
}
}