一、概念
1、组成
2、本质
路由的本质:一个路由表达了一组对应关系。路由器的本质:管理多组对应关系。
3、路由的工作原理
点击之后路径变化——>路由器监视到变化——>根据路径匹配路由——>完成切换
4、路由器的工作原理
不停的监视路径的变化,只要路径变化,路由器就会找到相应的路由,完成切换。
二、简单使用形式
1、安装 vue-router
2、main.js 中引入并使用 vue-router
导入:import VueRouter from 'vue-router',使用:Vue.use(VueRouter),
new Vue 时添加新的配置项:一旦使用了 vue-router 插件,添加一个全新的配置项:router。
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
//导入router插件
import VueRouter from 'vue-router'
//导入路由对象
import router from './router/index'
//使用插件
Vue.use(VueRouter)
new Vue({
el: '#app',
router: router,
render: h => h(App)
})
3、使用路由
在独立的js中创建路由器对象,并且将其暴露。然后在 main.js 文件中引入该路由器即可。
//导插件
import VueRouter from "vue-router";
//导组件
import HB from '../components/HB'
import HN from '../components/HN'
import CZ from '../components/CZ'
import SJZ from '../components/SJZ'
// 创建路由
const router = new VueRouter({
//配置多个路由
routes: [
{
path: '/hb',
component: HB,
children: [
{
path: 'cz',
component: CZ
},
{
path: 'sjz',
component: SJZ
}
]
},
{
path: '/hn',
component: HN
}
]
})
// 暴露路由
export default router
4、在App.vue 中使用 router-link 标签代替 a 标签
<template>
<div>
<div>
<h1>省份</h1>
<ul>
<!-- 如果使用的是路由方式,就不能使用超链接a标签了,需要使用vue-router插件提供的一个标签 -->
<!-- router-link 将来会被自动编译为a标签。 -->
<li>
<router-link to="/hb" active-class="selected">河北省</router-link>
</li>
<li>
<router-link to="/hn" active-class="selected">河南省</router-link>
</li>
</ul>
</div>
<!-- 路由视图,其实就是起到一个占位的作用。 -->
<keep-alive :include="[HB, HN]">
<router-view></router-view>
</keep-alive>
</div>
</template>
5、激活样式属性
<li>
<router-link to="/hn" active-class="selected">河南省</router-link>
</li>
6、指定组件的存放位置
路由视图,起到占位的效果
<router-view></router-view>
7、路由组件的两个属性
$route:属于自己的路由对象。 $router:多组件共享的路由器对象。
8、多级路由的使用
const router = new VueRouter({
//配置多个路由
routes: [
{
path: '/hb',
component: HB,
children: [
{
path: 'cz',
component: CZ
},
{
path: 'sjz',
component: SJZ
}
]
},
{
path: '/hn',
component: HN
}
]
})
注意:children里面的path属性不能加“/”
9、路由query的传参
目的是提高代码复用性
路由对象中有一个query属性,这个query属性可以接收query方式传递过来的数据。
this.$route.query
①直接传参
<li>
<router-link to="/hebei/city?a1=长安区&a2=裕华区&a3=新华区" active-class="selected">石家 庄 </router-link>
</li>
<li>
<router-link to="/hebei/city?a1=新华区&a2=运河区&a3=东光区" active-class="selected">沧州 </router-link>
</li>
②采用query方式传参,字符串拼接方式
<li>
<router-link :to="`/hebei/city?a1=${sjz[0]}&a2=${sjz[1]}&a3=${sjz[2]}`" active-class="selected">石家庄
</router-link>
</li>
<li>
<router-link :to="`/hebei/city?a1=${cz[0]}&a2=${cz[1]}&a3=${cz[2]}`" active-class="selected">邯郸
</router-link>
</li>
data() {
return {
sjz : ['长安区3', '裕华区2', '新华区2'],
cz : ['运河区', '新华区', '东光区']
}
},
③采用query方式传参,使用对象形式
<li>
<router-link active-class="selected" :to="{
path : '/hebei/city',
query : {
a1 : sjz[0],
a2 : sjz[1],
a3 : sjz[2],
}
}"> 石家庄</router-link>
</li>
data() {
return {
sjz : ['长安区', '裕华区', '新华区'],
cz : ['运河区', '新华区', '东光区']
}
},
10、params传参
<li>params方式传参:字符串形式,写死的字符串 -->
<router-link active-class="selected" to="/hebei/sjz/裕华区/新华区/长安区">石家庄
</router-link>
</li>
params方式传参:字符串形式,拼接字符串
<li>
<router-link active-class="selected" :to="`/hebei/sjz/${sjz[0]}/${sjz[1]}/${sjz[2]}`">石家庄</router-link>
</li>
params方式传参:对象形式
<li>
<router-link active-class="selected" :to="{
// 强调:如果使用的是params方式传参,这里只能使用name,不能使用path
name : 'shi',
params : {
a1 : sjz[0],
a2 : sjz[1],
a3 : sjz[2],
}
}">石家庄</router-link>
</li>
11、路由的props
props 配置主要是为了简化 query 和 params 参数的接收。让插值语法更加简洁。
①不是动态数据,将对象中的key和value通过props传给shi组件。
props : {
x : '张三',
y : '李四'
}
<li>{{x}}</li>
<li>{{y}}</li>
export default {
props:["x","y"]
}
②函数式方式
props($route){
return {
a1 : $route.params.a1,
a2 : $route.params.a2,
}
}
注:$route将来会被自动传过来,它代表了当前的路由对象。变量名随意的。
<li>{{a1}}</li>
<li>{{a2}}</li>
export default {
props:["a1","a2"]
}
12、栈的存储方式
push模式(默认):以追加的方式入栈。replace模式:以替换栈顶元素的方式。
开启replace模式
<router-link :replace=”true”/>
<router-link replace />
13、缓存路由组件
<keep-alive inclue=”组件名称”>
<router-view/>
</keep-alive>
不写 include 时:<router-view>包含的所有路由组件全部缓存。多个路由采用数组形式。
14、两个钩子函数(activated 和 deactivated)
只有“路由组件”有这两个生命周期钩子函数。
路由组件被切换到的时候,activated 被调用。 路由组件被切走的时候,deactivated 被调用。
三、路由守卫
1、全局前置守卫
router.beforeEach((to, from, next)=>{
<-- to
from
next -->
})
to:是从哪来(to.path,to.name);from:从哪来,next:调用next()。
2、全局后置路由
router.afterEach((to, from)=>{ //每次后(寓意:每一次切换路由后执行。)
// 没有 next
document.title = to.meta.title // 通常使用后置守卫完成路由切换时 title 的切换。
})
3、局部路由守卫之 path 守卫
beforeEnter(to, from, next){
let loginName = 'admin'
if(loginName === 'admin'){
next()
}else{
alert('对不起,您没有权限!')
}
},
没有afterEnter
4、局部路由守卫值component守卫
进入路由组件之前,必须是路由组件才能触发,普通组件不触发。
beforeRouteEnter(to, from, next){
console.log(city)
next()
},
离开路由组件之后,必须是路由组件才能触发,普通组件不触发。
beforeRouteleave(to, from, next){
console.log(city)
next()
},