6. vue-router
- 理解:一个路由(route)就是一组映射关系(key-value),多个路由需要路由器(router)进行管理
- 前端路由:key是路径,value是组件
6.1 路由基本使用
安装 vue-router
npm i vue-router@3
引入并使用
import VueRouter from 'vue-router'
Vue.use(VueRouter)
编写router配置项
import VueRouter from "vue-router";
import About from '../components/About.vue';
import Home from '../components/Home.vue';
// 创建一个路由器并暴露
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
实现切换
<router-link class="list-group-item"
active-class="active" to="/about">About</router-link>
指定展示位置
<router-view></router-view>
App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demo</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始html中我们使用a标签实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about.html">About</a> -->
<!-- <a class="list-group-item" href="./home.html">Home</a> -->
<!-- Vue中借助router-link标签实现路由的切换 -->
<router-link class="list-group-item"
active-class="active" to="/about">About</router-link>
<router-link class="list-group-item"
active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的呈现位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import AboutVue from './pages/About.vue'
import HomeVue from './pages/Home.vue'
export default {
name:'App',
components:{AboutVue, HomeVue}
}
</script>
<style scoped>
.active {
background-color: rgb(10, 193, 62);
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router';
import router from './router/index';
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
render: h => h(App),
router
}).$mount('#app')
几个注意点
- 路由组件通常存放在
pages
文件夹,一般组件通常存放在components
文件夹 - 通过切换,“隐藏”了的路由组件,默认是被销毁的,需要的时候再去挂载
- 每个组件都有自己的 r o u t e route route 属性,里面存储着自己的路由信息
- 整个应用只有一个router,可以通过组件的
$router
属性获取到
6.2 多级路由
-
配置路由规则,使用 children 配置项:
import VueRouter from "vue-router"; import About from '../pages/About.vue'; import Home from '../pages/Home.vue'; import Message from '../pages/Message.vue'; import News from '../pages/News.vue'; // 创建一个路由器并暴露 export default new VueRouter({ routes:[ { path:'/about', component:About, children:[ { path:'message', component:Message }, { path:'news', component:News } ] }, { path:'/home', component:Home } ] })
-
跳转 (要写完整路径)
<router-link class="list-group-item" active-class="active" to="/about/message">Message</router-link> <router-link class="list-group-item" active-class="active" to="/about/news">News</router-link> <router-view></router-view>
-
6.3 路由的query参数
-
传递参数
方式一 <router-link :to="{ path:'/about/news/detail', query:{ id: m.id, title: m.title } }" active-class="activate" > {{m.id + ' ' + m.title}} </router-link> 方式二 <router-link :to="`/about/message/detail?id=${m.id}&title=${m.title}`" active-class="activate" > {{m.id + ' ' + m.title}} </router-link>
-
接收参数
<h4>{{$route.query.id + ' ' + $route.query.title}}</h4>
6.4 命名路由
-
配置name
{ name:'detail', path:'detail', component:Detail }
-
简化跳转
<router-link :to="{ name:'detail', query:{ id: m.id, title: m.title } }" active-class="activate" > {{m.id + ' ' + m.title}} </router-link>
6.5 路由的params参数
-
配置路由,声明接收params参数
{ path:'news', component:News, children:[ { name:'detail', path:'detail/:id/:title', // 使用占位符声明接收params参数 component:Detail } ] }
-
传递参数
<!-- 跳转并携带params参数 to的对象写法 --> <router-link :to="{ name:'detail', params:{ id: m.id, title: m.title } }" active-class="activate" > {{m.id + ' ' + m.title}} </router-link> <!-- 跳转并携带params参数 to的字符串写法 --> <router-link :to="`/about/news/detail/${m.id}/${m.title}`" active-class="activate" > {{m.id + ' ' + m.title}} </router-link>
-
接收参数
<h4>{{$route.params.id + ' ' + $route.params.title}}</h4>
特别注意:路由携带params参数时若使用to的对象写法,则不能使用path配置项,必须使用name配置
6.6 路由的props配置
作用:让路由组件更方便的收到参数
{
name:'detail',
path:'detail', // 使用占位符声明接收params参数
component:Detail,
// 第一种写法:props值为对象,该对象所有的key-value组合最终都会通过props传给Detail组件
// props:{a:7978}
// 第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
// props:true
// 第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给 Detail组件
// props(route){
// return {
// id:route.query.id,
// title:route.query.title
// }
// }
// 简化写法1
// props({query}){
// return {
// id:query.id,
// title:query.title
// }
// }
// 简化写法2
props({query:{id, title}}){
return {
id, title
}
}
}
6.7 <router-link>
的replace属性
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式:分别为
push
和replace
,push
是追加历史记录,replace
是替换当前记录。路由跳转时候默认为push
- 如何开启
replace
模式:<router-link replace></router-link>
6.8 编程式路由导航
-
作用:不借助
<router-link>
实现路由跳转,让路由跳转更加灵活 -
具体编码
this.$router.push({ name:'detail', query:{ id: m.id, title: m.title } }) this.$router.replace({ name:'detail', query:{ id: m.id, title: m.title } }) // 前进 this.$router.forward() // 后退 this.$router.back() //跳转指定步数 this.$router.go(x) // x > 0 前进x步, x < 0 后退x步
6.9 缓存路由组件
-
作用:让不展示的路由组件保持挂载,不被销毁
-
具体编码
<keep-alive include="Message"> include 写组件名 <router-view></router-view> </keep-alive>
6.10 两个新的生命周期钩子
- 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态
- 具体名字:
activated
路由组件激活时触发deactivated
路由组件失活时触发
6.11 路由守卫
-
作用:对路由进行权限控制
-
分类:全局守卫,独享守卫,组件内守卫
-
全局守卫:
// 全局前置守卫:初始化时执行、每次路由切换前执行 vr.beforeEach((to, from, next)=>{ if (to.meta.login) { if (localStorage.getItem('login') == 'false') { console.log(to, from, next); alert('请登录') } else { next() } } else { next() } }) //全局后置守卫:初始化时执行、每次路由切换后执行 vr.afterEach((to, from)=>{ document.title = to.name })
-
独享守卫
beforeEnter(to, from, next){ if (to.meta.login) { if (localStorage.getItem('login') == 'false') { console.log(to, from, next); alert('请登录') } else { next() } } else { next() } }
-
组件内守卫:
// 进入守卫:通过路由规则,进入该组件被调用 beforeRouteEnter(to, from, next) { } // 离开守卫:通过路由规则,离开该组件时被调用 beforeRouteLeave(to, from, next) { }
-
6.12 路由器的两种工作模式
- 对于一个url来说,什么是hash值?————#及其后的内容就是hash值
- hash值不会包含在HTTP请求中,即:hash值不会带给服务器
- hash模式:
- 地址中永远带着#号,不美观
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
- 兼容性较好
- history模式:
- 地址干净,美观
- 兼容性和hash模式相比较差
- 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题