VUE笔记(六)vue路由

一、路由的简介

1、实现生活中的路由

路由:路由其实就是一个key-value对应关系

路由器:用于管理多个路由关系的设备被称为路由器

2、前端的路由

目前使用的前端项目都是单页面的应用(SPA),一个项目中只有一个html页面,这种项目是由很多个组件组成,组件之间如果要跳转要依靠路由来完成,路由是由key和value组成一个对应关系,前端路由的key就是url地址,路由的value就是组件本身

keyvalue
http://localhost:8080/loginLogin.vue
http://localhost:8080/registerRegister.vue

总之:路由是实现多个组件之间进行跳转一种方式,使用路由将各组件之间联系起来

由于vue是一个渐进式的前端框架,vue的核心语法中不包括路由,路由以插件的形式存在,如果要去使用路由就要去将路由集成到vue项目中

二、路由的基本配置

1、路由的配置

由于路由不是vue的核心功能,大家如果要使用就需要去单独集成它,在vue中使用路由最多一个路由产品vue-router

vue-router的官网:Vue Router

注意:vue2的项目,匹配的路由版本是vue-router@3

配置的具体步骤如下

  • 安装vue-router的依赖包

npm install vue-router@3.5.1
  • 在src目录创建router的文件夹,在router文件夹下创建index.js文件,具体代码如下

//导入Vue包
import Vue from 'vue'
//导入VueRouter包
import VueRouter from 'vue-router'
//将VueRouter作为插件设置到Vue中
Vue.use(VueRouter)
//创建路由器对象
const router=new VueRouter()
//将这个路由器对象导出
export default router
  • 将路由挂载到vue实例上,在main.js文件中

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的对应关系

  • 创建组件

    在src/views目录下分别创建Login.vue、Register.vue、Home.vue

  • 路由配置

    在src/router/index.js进行如下配置

//导入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根组件中配置路由出口

<template>
    <router-view></router-view>
</template>
4、路由的跳转

使用vue-router进行路由跳转有两种方式

  • 标签式跳转方式:使用<router-link>这个标签进行跳转,一般使用在<template></template>模板之中,最终会编译成<a>标签

  • 编程式跳转方式:使用this.$router对象的push或者replace方法进行跳转的,这种跳转方式一般使用在组件的js代码部分

4.1、标签式路由跳转的案例
已有账号?<router-link to="/login">前往登录</router-link>
4.2、编程式路由跳转
  • 下载axios

npm i axios
  • 配置package.json

"scripts": {
    "serve": "vue-cli-service serve",
    "serve:production": "set NODE_ENV=production&vue-cli-service serve",
    "build": "vue-cli-service build"
 }
  • 封装auth.js方法,完成token获取和设置的封装

    位置:src/utils/auth.js

const tokenkey="admin-token"
// 保存token到localStorage中的方法
export const setToken=tokenval=>localStorage.setItem(tokenkey,tokenval)
// 从localStorage中获取token
export const getToken=()=>localStorage.getToken(tokenkey)
  • 封装axios

位置: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
  • 编写登录api方法

位置: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
}
  • 挂载api到Vue原型上

位置:src/main.js

import api from '@/api/api'
Vue.prototype.$api=api
  • 组件中完成登录

位置:src/views/Login.vue

<template>
    <div>
        <h1>登录</h1>
        <div>
            没有账号?<router-link to="/register">前往注册</router-link>
        </div>
        <div>
            <div>
                <label for="username">姓名:</label>
                <input id="username" type="text" placeholder="请输入登录账户" v-model="user.username">
            </div>
             <div>
                <label for="password">密码:</label>
                <input id="password" type="text" placeholder="请输入登录账户" v-model="user.password">
            </div>
            <div>
                <button @click="login">登录</button>
            </div>
        </div>
    </div>
</template>

<script>
import {setToken} from '@/utils/auth'
export default {
    data(){
        return{
            user:{
                username:'admin',
                password:'123'
            }
        }
    },
    methods:{
        async login(){
           let {code,message,token}=await this.$api.users.login(this.user)
           /* 
             登录成功后,要完成的事项有两个
             1、保存token到localStorage中
             2、使用路由进行跳转
           */
          setToken(token)
          if(code){
            alert(message)
            //跳转到后台,使用编程式路由跳转
            this.$router.replace('/home')
          }
        }
    }
}
</script>

<style>

</style>
5、路由的嵌套
  • 如果要配置二级路由,需要在相应的一级路由对象上添加children属性,然后进行配置

位置: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

<template>
    <div class="container">
       <div class="header">
            <div class="logo">学苑BOSS系统</div>
       </div>
       <div class="main">
            <div class="silder">
                <ul>
                    <li>
                        <span>控制面板</span>
                        <ul class="sul">
                            <li>
                                <router-link to="/home/workplace">工作台</router-link>
                            </li>
                            <li>
                                <router-link to="/home/analysis">统计报表</router-link>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <span>学员管理</span>
                        <ul class="sul">
                            <li>
                                <router-link to="/home/studentList">学生列表</router-link>
                            </li>
                        </ul>
                    </li>
                    <li>
                        <span>系统管理</span>
                        <ul class="sul">
                            <li>班主任管理</li>
                            <li>教师管理</li>
                            <li>专业管理</li>
                            <li>班级管理</li>
                        </ul>
                    </li>
                </ul>
            </div>
            <div class="content">
                <!-- 设置二级路由的出口 -->
                <router-view></router-view>
            </div>
       </div>
    </div>
</template>

<script>
export default {

}
</script>

三、路由的其他配置

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'
}
  • 在路由的出口的地方设置keep-alive

 <keep-alive exclude="analysis">
         <router-view></router-view>
 </keep-alive>
  • exclude:该组件不被缓存

  • include:该组件会被缓存

4、路由的元信息

路由对象有很多属性,核心有两个,一个就是path,表示的路由的路径,component表示的是路由的对应的组件,除此之外还有其他的属性,比如meta属性,可以设置路由的额外信息,这里以两个例子给大家讲解

4.1、面包屑的功能
  • 需要在路由定义的时候在相应的路由配置对象中添加meta属性,配置面包屑的具体配置

{
       path:'workplace',//二级路由的path的前不要带/
       component:()=>import('@/views/dashboard/workplace.vue'),
       meta:{
          firstTitle:'控制面板',
          secondTitle:'工作台'
      }
},
  • 自定义面包屑组件

在src/components目录下创建BreadCrumb组件

<template>
    <div>
        <span>{{$route.meta.firstTitle}}</span>&gt;<span>{{$route.meta.secondTitle}}</span>
    </div>
</template>
  • 在需要的组件中引入面包屑组件

<template>
    <div>
        <bread-crumb></bread-crumb>
        <h1>学生列表</h1>
    </div>
</template>
4.2、路由缓存状态设置
  • 在路由配置中为meta属性设置isKeepAlive属性

{
        path:'workplace',//二级路由的path的前不要带/
        component:()=>import('@/views/dashboard/workplace.vue'),
        meta:{
            firstTitle:'控制面板',
            secondTitle:'工作台',
            iskeepAlive:true
      }
 },
  • 在路由出口的地方通过v-if指令来完成设置

 <keep-alive>
    <router-view v-if="$route.meta.iskeepAlive"></router-view>
 </keep-alive>
 <router-view v-if="!$route.meta.iskeepAlive"></router-view>

说明:这种设置方式较之前使用include或者exclude方式的更加合理。

四、路由传参

1、学生列表
  • 编写获取学生的api方法

import request from '@/api/request'
export default{
    getStudents:params=>request.get('/students/getStudents',{params})
}
  • 汇总api

import users from "./modules/users";
import students from "./modules/students";
export default{
    users,students
}
2、query传参

vue-router这个路由操作中,要进行传参有多种方式,比较常用的方式有两种

  • query传参方式

  • params传参方式

query传参的步骤

第1步:创建页面组件,配置路由

 {
        path:'studentDetail',
        component:()=>import('@/views/students/studentDetail.vue'),
        meta:{
            firstTitle:'学生管理',
            secondTitle:'学生详情'
        }
 }

第2步:进行传参

  • 标签跳转的方式

<router-link :to="`/home/studentDetail?_id=${item._id}`"><button class="btn detal">查看</button></router-link>
<router-link :to="'/home/studentDetail?_id='+item._id"><button class="btn detal">查看</button></router-link>
<router-link :to="{path:'/home/studentDetail',query:{_id:item._id}}"><button class="btn detal">查看</button></router-link>
//命名路由
<router-link :to="{name:'xsxq',query:{_id:item._id}}"><button class="btn detal">查看</button></router-link>

最后一种写法是使用了命名路由的写法,命名路由的好处就是使用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

面试题(简单的面试题)

  • router:它是一个VueRouter类型的一个对象,通过new VueRouter构造函数方式将其创建出来,它是一个全局对象

    • 设置路由模式

    • 实现路由跳转:通过该对象中push或者replace方法来实现跳转的

  • route:路由信息对象,它属于一个局部对象,该对象主要用来描述路由信息的

    • 获取该路由path路径

    • 获取该路由的传递的参数(query参数,params参数)

    • 获取该路由的meta信息(用户自定义的信息)

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步:路由跳转传参

根据跳转方式的不同

  • 标签方式跳转

 <router-link :to="`/home/studentUpdate/${item._id}`"><button class="btn detal">修改</button></router-link>
 <router-link :to="'/home/studentUpdate/'+item._id"><button class="btn detal">修改</button></router-link>
  • 编程方式跳转

 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参数有两个方法

  • 使用this.$route.params.参数名

 console.log(this.$route.params.id);
  • 使用props方式传参

配置步骤

首先:在路由对象设置可以使用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、修改学生
  • 页面返回和页面刷新

<button @click="$router.go(-1)">返回</button>
<button @click="$router.go(0)" >刷新</button>

五、路由模式【面试题】

由于Vue项目为单页面应用,所以整个项目在开发和构建过程中,仅存在一个HTML物理文件,通过路由系统可以实现将项目的组件与可访问的URL路径进行绑定。由于Vue项目只有一个HTML物理文件,切换页面时既需要让访问的URL路径发生变化,又不能触发HTML物理文件的重新加载,这就使得VueRouter的跳转模式不能使用普通的超链接方式。

VueRouter为了支持单页面应用的页面管理和页面跳转,提供了两种页面跳转和加载模式:

  • hash:在浏览器 URL 路径中会有一个'#'

  • history:在浏览器 URL 路径中没有'#'

1、hash模式

hash模式使用了锚点技术重写URL访问路径,会在原有的URL路径后拼接/#/xx,这种方式可以在不重新加载原有HTML文件的基础上,实现切换URL路径的目的,hash模式的原理案例,代码如下

<a href="#/index">首页</a>
    <a href="#/about">关于我们</a>
    <div class="page index">
        我是首页
    </div>
    <div class="page about">
        我是关于页面
    </div>
    <script>
        window.onhashchange=function(event){
            var newURL=event.newURL.split("#/")[1]
            var oldURL=event.oldURL.split("#/")[1]
            var newPage=document.querySelector('.'+newURL)
            var oldPage=document.querySelector('.'+oldURL)
            newPage.style.display="block"
            oldPage.style.display="none"
        }
    </script>

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的原理,代码如下

 <a href="javascript:jump('/index')">跳转到首页</a>
    <a href="javascript:jump('/about')">跳转到about页</a>
    <div class="page index">
        我是首页
    </div>
    <div class="page about">
        我是关于页面
    </div>
    <script>
       function jump(path){
        history.pushState(null,'page',path)
        var pages=document.querySelectorAll('.page')
        var newPage=document.querySelector(path.replace("/","."))
        pages.forEach(item=>item.style.display='none')
        newPage.style.display='block'
       }
    </script>

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)=>{
    
})

参数说明:

  • 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()
           }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值