本文已参与[新人创作礼]活动,一起开启掘金创作之路。
路由理解
路由
1.一组路由就是一组key-value的映射关系。
2.key为路径,value可能是函数和组件。
路由分类
路由分为前端路由和后端路由。
前端路由:
1.value为组件,展示相关组件内容。
2.当浏览器的路径改变时,对应的组件就会显示。
后端路由:
1.value为函数,用于处理客户端提出的请求。
2.服务器接收一个请求时,会根据请求路径找到匹配的函数来处理相关请求,返回响应数据。
下载路由插件vue-router
vue-router是vue的一个插件库,专门用来实现SPA(单页面Web应用)。
下载插件:
现在默认的是4版本,vue-router 4只能在vue3中使用,而vue-router 3,可以在vue2中使用。
npm install vue-router@3 --save-dev
因为路由是展示组件相关内容,所以写了两个组件StudentList和SchoolList;
在项目src目录下创建router目录,在router目录下创建index.js文件。
并写一些基础配置
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
//全部路由
routes: [
{
path: '/student',
component: StudentList
},
{
path: '/school',
component: SchoolList
}
]
})
在main.js中配置路由文件
import Vue from 'vue'
import App from './App.vue'
import VueLazyLoad from 'vue-lazyload'
// 引入路由文件
import router from '@/router/index'
Vue.config.productionTip = false
// Vue.use(VueLazyLoad)
Vue.use(VueLazyLoad, {
preLoad: 1.3,
error: require('./assets/img/logo.png'),
loading: require('./assets/img/logo.png'),
attempt: 1
})
new Vue({
// 配置router
router,
render: h => h(App),
}).$mount('#app')
路由就配置成功了。
less和less-loader插件安装
这里由于CSS样式使用less,所以需要安装less 和less-loader插件。
注意版本问题,否则运行项目会报错。在vue2中使用以下版本不会报错。
npm install less@3.9.0 -s
npm install less-loader@5.0.0 -s
router-link
路由导航,实现切换。
App.vue中添加:
<router-link class="link-show" active-class="active" to="/student">学生列表</router-link>
<router-link class="link-show" active-class="active" to="/school">学校列表</router-link>
to跳转的地址就是在路由文件里面配置的path,router-link相当于一个a标签,如果想改变其类型,可添加tag属性,如改成按钮:
<router-link class="link-show" tag="button" active-class="active" to="/student">学生列表</router-link>
<router-link class="link-show" tag="button" active-class="active" to="/school">学校列表</router-link>
router-view
路由视图,指定展示位置。
App.vue中添加:
<router-view></router-view>
App.vue完整代码:
<template>
<div id="app">
<!-- 路由导航,实现切换 -->
<div>
<router-link class="link-show" active-class="active" to="/student">学生列表</router-link>
<router-link class="link-show" active-class="active" to="/school">学校列表</router-link>
</div>
<!-- 路由视图,指定展示位置 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style lang="less">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
.active{
background: #2866f9;
border-radius: 2px;
}
.link-show{
display: inline-block;
border: 1px solid;
width: 100px;
height: 20px;
text-decoration: none;
}
}
</style>
点击切换,会显示相应组件的内容。
通过切换,隐藏的路由组件是被销毁了,需要时再挂在。
每个组件都有自己的$route属性,里面存储自己的路由信息。
整个应用只有一个$router。
一个基础的路由切换就完成了,是根据路由规则去匹配相关路由。当然,如果是完整的一个项目,在路由文件中就会有很多其他的设置。
路由文件基础配置
这里主要介绍了嵌套路由、路由模式。
嵌套路由(多级路由)
嵌套路由又称子路由、多级路由,在实际应用中,通常由多层嵌套的组件组合而成。
这里是给学校组件加子路由ClassInfo和TeacherInfo组件。
首先,需要在路由文件中把路由规则写好。
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
//全部路由
routes: [
{
path: '/student',
component: StudentList
},
{
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
path: 'class', // 不要写成/class
component: ClassInfo
},
{
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
}
]
}
]
})
然后,再去学校组件配置:
SchoolList.vue
<template>
<div class="school-info">
这是学校组件
<div>
<router-link class="link-show" active-class="active" to="/school/class">班级信息</router-link>
<router-link class="link-show" active-class="active" to="/school/teacher">老师信息</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'SchoolList'
}
</script>
<style lang="less">
.school-info{
.link-show{
display: inline-block;
border: 1px solid;
width: 100px;
height: 20px;
text-decoration: none;
}
}
</style>
注意,router-link里面的to是要从第一级写,要写完整路径,即/school/class。
选择学生列表,展示学生组件的内容:
选择学校列表,班级信息路由和老师信息路由就展示出来了:
选择班级信息,展示班级组件的内容:
选择老师信息,展示老师组件的内容:
路由模式
vue的路由模式分为hash和history,默认为hash模式。
在访问上面的vue项目时,我们观察访问地址,可以看见地址里面带有一个#号:
从#开始的所有东西,都叫url的hash值。hash值的特点就是不会随着http请求发给服务器,即不会作为请求资源传给服务器。
默认为hash模式,如果想要用history模式,则需要在路由文件中配置mode选项:
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
path: '/student',
component: StudentList
},
{
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
path: 'class', // 不要写成/class
component: ClassInfo
},
{
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
}
]
}
]
})
此时访问时,就没有#:
比较:
hash模式: 1.地址中有#。 2.若将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。 3.兼容性较好。
history模式: 1.地址中没有#。 2.兼容性相比于hash模式较差。 3.应用部署上线时需要nginx代理或者后端人员处理,解决刷新页面服务端404的问题。
路由传参-query
1.跳转路由时携带参数,使用to的字符串写法,因为参数是动态的,所以需要动态绑定to。
<router-link class="link-show" active-class="active" :to="`/school/teacher?id=${id}&name=${name}`">老师信息</router-link>
2.跳转路由时携带参数,使用to的对象写法。
<router-link class="link-show" active-class="active"
:to="{
path:'/school/teacher',
query: {
id:id,
name:name
}
}">
老师信息
</router-link>
使用query传参,不会影响路由文件配置index.js。
teacher组件接收参数:
$route.query.id
$route.query.name
路由传参-params
使用params传参,使用to的字符串写法。
<router-link class="link-show" active-class="active" :to="`/school/teacher/${id}/${name}`">老师信息</router-link>
需要去路由文件中设置占位符,不然参数就会被路由层级。
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
// params传参,使用占位符声明接收参数
path: 'teacher/:id/:name',// 不要写成/teacher
component: TeacherInfo,
}
]
}
]
})
使用params传参,使用to的对象写法。
<router-link class="link-show" active-class="active"
:to="{
name:'teacher',
params: {
id:id,
name:name
}
}">
老师信息
</router-link>
注意:路由携带params参数时,若使用to的对象写法,则必须使用name配置。
使用query传参,需要在路由文件配置index.js相应路由上使用占位符声明接收参数。
teacher组件接收参数:
$route.params.id
$route.params.name
路由的命名空间
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
}
]
}
]
})
使用命名时,在路由跳转或带参数跳转时可以简化一些代码。
将
<router-link class="link-show" active-class="active" to="/school/teacher">老师信息</router-link>
换成
<router-link class="link-show" active-class="active" :to="{name:'teacher'}">老师信息</router-link>
带参数跳转时,使用name。
<router-link class="link-show" active-class="active"
:to="{
name:'teacher',
query: {
id:id,
name:name
}
}">
老师信息
</router-link>
路由传参-props
使用props读取参数简单,不用route.params.name。
这里对teacher组件的路由进行props设置。
props的值为对象
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
// props第一种写法,值为对象,对象里面的所有key-value都会以props的形式传给teacher组件。
props:{id:1,name:'props对象写法'}
}
]
}
]
})
参数接受,则直接props接收。
teacher组件
<template>
<div>
这是学校里面老师的信息+{{this.id}}+{{this.name}}
</div>
</template>
<script>
export default {
name: 'TeacherInfo',
props:['id','name']
}
</script>
<style lang="less">
</style>
props的值布尔值
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
// params传参
path: 'teacher/:id/:name',// 不要写成/teacher
component: TeacherInfo,
// props第二种写法,值为布尔值,若布尔值为真就会把该路由组件收到的所有params参数以props的形式传给teacher组件。
props: true
}
]
}
]
})
teacher组件
<template>
<div>
这是学校里面老师的信息+{{this.id}}+{{this.name}}
</div>
</template>
<script>
export default {
name: 'TeacherInfo',
props:['id','name']
}
</script>
<style lang="less">
</style>
props的值为函数
第二种方法是params传参才能使用,这种方法能够使用$route,params传参和query传参都能传递参数到组件。
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
// props第三种写法,值为函数,return返回一个对象的每一组key-value以props的形式传给teacher组件。
props(route){
return{
id: route.query.id,
name: route.query.name
}
}
}
]
}
]
})
也可使用解构赋值的写法:
props({query}){
return{
id: query.id,
name: query.name
}
}
teacher组件
<template>
<div>
这是学校里面老师的信息+{{this.id}}+{{this.name}}
</div>
</template>
<script>
export default {
name: 'TeacherInfo',
props:['id','name']
}
</script>
<style lang="less">
</style>
router-link的replace属性
浏览器历史记录的写入方式,push是追加历史记录,replace是替换当前记录。
router-link路由跳转时默认的是push模式(可前进后退)。
开启replace模式:
班级信息
编程式路由导航
编程式路由导航是一种全新的路由方式。
不用router-link实现路由的跳转,让路由跳转更加灵活。
push方式:
this.$router.push({
name:'student',
query: {
id: 888,
name: 888
}
})
replace方式:
this.$router.replace({
name:'student',
query: {
id: 888,
name: 888
}
})
params传参,当页面刷新时,参数丢失。可在路由文件相关路由下配置占位符,刷新页面后参数不丢失。
query传参,数据会出现在url上面。
若query里面是个对象,需要先使用JSON.stringify()转换成字符串,收参数的页面需要使用JSON.parse()将字符串转换成对象。
前进:this.$router.forward();
后退:this.$router.back();
前进或者后退指定步数(负数后退,正数前进):this.$router.go(6);
缓存路由组件
让不展示的路由组件保持挂载不被销毁。
缓存1个路由组件
<keep-alive include="TeacherInfo">
<router-view></router-view>
</keep-alive>
缓存多个路由组件
<keep-alive :include="['TeacherInfo','StudentInfo']">
<router-view></router-view>
</keep-alive>
不写include,表示在里面显示的组件全部缓存。
写include时,里面写组件名,表示只缓存该组件。exclude表示里面的不缓存。
同样,可以在路由文件index.js中配置:
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
export default new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList,
meta:{
keepAlive:false
},
},
{
name: 'school',
path: '/school',
component: SchoolList,
meta:{
keepAlive:false
},
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo,
meta:{
keepAlive:false
},
},
{
name: 'teacher',
path: 'teacher',
component: TeacherInfo,
// 使用路由中的meta属性来控制路由缓存
meta:{
keepAlive:true
},
}
]
}
]
})
这里是把teacher路由的meta属性设置为keepAlive:true,表示当前组件要进行缓存,然后:
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
里面包含需要缓存的组件
<keep-alive>
<!-- 动态组件 -->
<component />
</keep-alive>
对于缓存路由组件,这篇文章讲得很好:juejin.cn/post/684490…
生命周期activated和deactivated
因为使用缓存组件后,该组件
路由组件所独有的两个钩子:activated和deactivated。
activated:路由组件被激活时触发。
deactivated:路由组件停用时触发。
keep-alive对组件进行了缓存所以并不会再一次执行创建和挂载。
简单的说activated()函数就是一个页面激活后的钩子函数,一进入页面就触发;
所以当我们运用了组件缓存时,如果想每次切换都发送一次请求的话,需要把请求函数写在activated中,而写在created或mounted中其只会在首次加载该组件的时候起作用。deactivated是离开组件时被触发,而写在beforeDestroy中的不会被触发。
在第一次进入页面时,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。如下图所示:
缓存的路由组件实现文字透明度的变化
<template>
<div>
<span :style="{opacity}">
这是学校里面老师的信息+{{this.id}}+{{this.name}}
</span>
<input type="text"/>
</div>
</template>
<script>
export default {
name: 'TeacherInfo',
props:['id','name'],
data(){
return{
opacity: 1
}
},
activated(){
console.log('activated');
this.timer = setInterval(()=>{
this.opacity -= 0.01;
if(this.opacity <= 0) this.opacity = 1;
},16)
},
deactivated(){
console.log('deactivated');
clearInterval(this.timer);
}
}
</script>
<style lang="less">
</style>
路由守卫
全局前置路由守卫
全局前置路由守卫是在初始化的时候被调用或路由切换前被调用。
在路由文件index.js中调用路由的beforeEach。
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
const router = new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
meta: {
keepAlive: true
},
// props第三种写法,值为函数。
props({query}){
return{
id: query.id,
name: query.name
}
}
}
]
}
]
})
// 全局前置路由
router.beforeEach((to,from,next)=>{
console.log(to,from)
})
export default router
在beforeEach中有to,from,next。
比如从班级组件进入到老师组件,to和from打印出来的信息:
to为到达组件的信息,from是从哪个组件切换的信息。主要包括组件路径和组件名。
比如在本地储存中有一个职位信息,当从学生组件进入到老师组件时,判断职位是否为教师(isTeacher),其他组件切换不做要求,若不是则提示不能进入。
// 全局前置路由
router.beforeEach((to,from,next)=>{
// 可以使用path也可以使用name,这里使用name。
if( to.name == 'teacher' && from.name == 'student' && localStorage.getItem('degree') !== 'isTeacher'){
alert('你不是老师,学生不能进入!');
}else{
// 放行
next();
}
})
比如在本地储存中有一个学校信息,当进入到班级组件或老师组件时,判断学校是否为university,其他组件切换不做要求,若不是则提示学校不是university。
// 全局前置路由
router.beforeEach((to,from,next)=>{
// 可以使用path也可以使用name,这里使用name。
if( to.name == 'teacher' || to.name == 'class' ){
// 判断信息
if(localStorage.getItem('schoolInfo') == 'university'){
// 消息正确放行路由
next();
}else{
// 消息不正确,拦截路由跳转。
alert('学校不是university');
}
}else{
// 放行
next();
}
})
当路由限制过多时,to.name == 'teacher' || to.name == 'class' || ...就太多了,这里可以给每个路由设置一个属性,当该属性值为某个值时,再做路由的限制。
在这里就要知道路由元信息meta,这里面就可以放一些自定义的信息。需要权限的路由就设置meta,不需要权限的路由就不需要meta,因为没有这个属性就是undefined,就为false。
通过meta来设置进入teacher和class路由权限:
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
const router = new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList
},
{
name: 'school',
path: '/school',
component: SchoolList,
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo,
meta: {
isAuth: true,
},
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
meta: {
keepAlive: true,
isAuth: true,
},
// props第三种写法,值为函数。
props({query}){
return{
id: query.id,
name: query.name
}
}
}
]
}
]
})
// 全局前置路由
router.beforeEach((to,from,next)=>{
// 使用meta的isAuth属性判断
if( to.meta.isAuth){
// 判断信息
if(localStorage.getItem('schoolInfo') == 'university'){
// 消息正确放行路由
next();
}else{
// 消息不正确,拦截路由跳转。
alert('学校不是university');
}
}else{
// 放行
next();
}
})
export default router
其中,next参数的使用如下所示:
next() // 路由正常跳转。
next('/') // 回到首页。
next(false) // 在当前路由不跳转。
next(to.path) // 强制跳转至指定路由。
全局后置路由守卫
全局后置路由守卫是在初始化的时候被调用或路由切换后被调用。
比如切换成功后把标题改为切换后的那个组件对应的名字。先在meta中配置title属性,再在后置路由守卫中设置,当然前置路由守卫也可以设置,但是需要判断,没有后置守卫简单。
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
const router = new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList,
meta: {
title: '学生'
}
},
{
name: 'school',
path: '/school',
component: SchoolList,
meta: {
title: '学校'
},
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo,
meta: {
isAuth: true,
title: '班级'
},
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
meta: {
keepAlive: true,
isAuth: true,
title: '老师'
},
// props第三种写法,值为函数。
props({query}){
return{
id: query.id,
name: query.name
}
}
}
]
}
]
})
// 全局前置路由
router.beforeEach((to,from,next)=>{
// 使用meta的isAuth属性判断
if( to.meta.isAuth){
// 判断信息
if(localStorage.getItem('schoolInfo') == 'university'){
// 消息正确放行路由
next();
}else{
// 消息不正确,拦截路由跳转。
alert('学校不是university');
}
}else{
// 放行
next();
}
})
// 全局后置路由
router.afterEach((to,from)=>{
console.log(to,from);
// 路由切换成功后设置当前标题,当meta.title不存在时,标题名为系统名字。
document.title = to.meta.title || '系统名字';
})
export default router
独享路由守卫
独享路由守卫是某个路由独享的。如只设置进入老师组件时的路由权限设置,就在老师组件路由设置beforeEnter。里面代码实现逻辑和前置路由守卫是一样的。
路由文件index.js
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
const router = new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList,
meta: {
title: '学生'
}
},
{
name: 'school',
path: '/school',
component: SchoolList,
meta: {
title: '学校'
},
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo,
meta: {
isAuth: true,
title: '班级'
},
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
meta: {
keepAlive: true,
isAuth: true,
title: '老师'
},
// props第三种写法,值为函数。
props({query}){
return{
id: query.id,
name: query.name
}
},
// 独享路由守卫
beforeEnter: ((to, from, next) => {
console.log(to,from);
if( to.meta.isAuth){
// 判断信息
if(localStorage.getItem('degree') == 'isTeacher'){
// 消息正确放行路由
next();
}else{
// 消息不正确,拦截路由跳转。
alert('你不是老师,学生不能进入!');
}
}else{
// 放行
next();
}
})
}
]
}
]
})
// // 全局前置路由
// router.beforeEach((to,from,next)=>{
// // 使用meta的isAuth属性判断
// if( to.meta.isAuth){
// // 判断信息
// if(localStorage.getItem('schoolInfo') == 'university'){
// // 消息正确放行路由
// next();
// }else{
// // 消息不正确,拦截路由跳转。
// alert('学校不是university');
// }
// }else{
// // 放行
// next();
// }
// })
// 全局后置路由
router.afterEach((to,from)=>{
console.log(to,from);
// 路由切换成功后设置当前标题,当meta.title不存在时,标题名为系统名字。
document.title = to.meta.title || '系统名字';
})
export default router
组件内路由守卫
组件内路由守卫,beforeRouteEnter和beforeRouteLeave。
beforeRouteEnter:进入守卫,通过路由规则,进入该组件时被调用。
beforeRouteLeave:离开守卫,通过路由规则,离开该组件时被调用。
路由文件index.js:
// 该文件用于创建整个应用的路由器
// 引入Vue
import Vue from "vue";
// 引入路由插件
import VueRouter from "vue-router";
// 引入组件
import StudentList from '@/components/StudentList'
import SchoolList from '@/components/SchoolList'
import ClassInfo from '@/components/ClassInfo'
import TeacherInfo from '@/components/TeacherInfo'
//使用插件
Vue.use(VueRouter);
// 创建一个路由器并暴露出去
const router = new VueRouter({
// 设置路由模式
mode:'history',
//全部路由
routes: [
{
name: 'student', //名字自定义,不受其他参数影响。
path: '/student',
component: StudentList,
meta: {
title: '学生'
}
},
{
name: 'school',
path: '/school',
component: SchoolList,
meta: {
title: '学校'
},
// 通过设置children配置子级路由
children:[
{
name: 'class',
path: 'class', // 不要写成/class
component: ClassInfo,
meta: {
isAuth: true,
title: '班级'
},
},
{
name: 'teacher',
// params传参
path: 'teacher',// 不要写成/teacher
component: TeacherInfo,
meta: {
keepAlive: true,
isAuth: true,
title: '老师'
},
// props第三种写法,值为函数。
props({query}){
return{
id: query.id,
name: query.name
}
},
}
]
}
]
})
export default router
teacher组件
<template>
<div>
<span :style="{ opacity }">
这是学校里面老师的信息+{{ this.id }}+{{ this.name }}
</span>
<input type="text" />
</div>
</template>
<script>
export default {
name: 'TeacherInfo',
props:['id','name'],
data(){
return{
opacity: 1
}
},
activated(){
console.log('activated');
this.timer = setInterval(()=>{
this.opacity -= 0.01;
if(this.opacity <= 0) this.opacity = 1;
},16)
},
deactivated(){
console.log('deactivated');
clearInterval(this.timer);
},
// 通过路由规则,进入该组件时被调用。
beforeRouteEnter(to,from,next){
console.log(to,from,next);
//使用meta的isAuth属性判断
if( to.meta.isAuth){
// 判断信息
if(localStorage.getItem('degree') == 'isTeacher'){
// 消息正确放行路由
next();
}else{
// 消息不正确,拦截路由跳转。
alert('你不是老师,学生不能进入!');
}
}else{
// 放行
next();
}
},
// 通过路由规则,离开该组件时被调用。
beforeRouteLeave(to,from,next) {
console.log(to,from,next);
next();
}
}
</script>
<style lang="less">
</style>