22. 路由(Vue-Router)
22.1 基本使用
- 安装vue-router, 命令:
npm i vue-router
- 应用插件:
Vue.use(VueRouter)
编写router配置项:
src/router/index.js
//引入VueRouter import VueRouter from 'vue-router' //创建router实例对象并暴露 export default new VueRouter({ //管理一组一组的路由规则 routes:[ { //导航路径 path:"/home", component:()=>import('../components/Home') }, { path:"/about", component:()=>import('../components/About') } ] })
实现切换(active-class可配置高亮样式)
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link> <router-link class="list-group-item" active-class="active" to="/about">About</router-link>
指定展示位置
<router-view></router-view>
22.2几个注意点
- 路由组件通常存放在
pages
文件夹,一般组件通常存放在components
文件夹 - 通过切换,'隐藏'了的路由组件,默认是被销毁掉的,需要的时候再去挂载
- 每个组件都有自己的
$route
属性,里面存储这自己的路由信息 - 整个应用只有一个
router
,可以通过组件的$router
属性获取到
22.3 嵌套路由(多级路由)
- 配置路由规则,使用children配置项:
routes:[ { //导航路径 path: "/home", component: () => import('../pages/Home'), children:[ { path:"news", component:()=>import('../pages/News') }, { path:"message", component:()=>import('../pages/Message') } ] }, { path:"/about", component:()=>import('../pages/About') } ]
- 跳转(要写完整路径):
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
22.4 路由的query参数
传递参数
Message.vue
<template> <div> <ul> <li v-for="m in messageList" :key="m.id"> <!--跳转路由并携带query参数(to的字符串写法)--> <!--<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>--> <!--跳转路由并携带query参数(to的对象写法)--> <router-link :to="{ path:'/home/message/detail', query:{ id:m.id, title:m.title } }">{{m.title}}</router-link> </li> </ul> <router-view></router-view> </div> </template> <script> export default { name: "Message", data() { return { messageList: [ {id: "001", title: "消息001"}, {id: "002", title: "消息002"}, {id: "003", title: "消息003"}, ] } } } </script> <style scoped> </style>
接收参数
Detail.vue
<template> <ul> <li>消息编号: {{ $route.query.id }}</li> <li>消息标题: {{ $route.query.title }}</li> </ul> </template> <script> export default { name: "Detail" } </script> <style scoped> </style>
src/router/index.js
//引入VueRouter import VueRouter from 'vue-router' //创建router实例对象并暴露 export default new VueRouter({ //管理一组一组的路由规则 routes:[ { //导航路径 path: "/home", component: () => import('../pages/Home'), children:[ { path:"news", component:()=>import('../pages/News') }, { path:"message", component:()=>import('../pages/Message'), children:[ { path:"detail", component:()=>import('../pages/Detail') } ] } ] }, { path:"/about", component:()=>import('../pages/About') } ] })
22.5 命名路由
- 作用: 可以简化路由的跳转
如何使用
给路由命名:
//引入VueRouter import VueRouter from 'vue-router' //创建router实例对象并暴露 export default new VueRouter({ //管理一组一组的路由规则 routes:[ { name:"home", //导航路径 path: "/home", component: () => import('../pages/Home'), children:[ { name:"news", path:"news", component:()=>import('../pages/News') }, { name:'message', path:"message", component:()=>import('../pages/Message'), children:[ { name:"detail", path:"detail", component:()=>import('../pages/Detail') } ] } ] }, { path:"/about", component:()=>import('../pages/About') } ] })
简化跳转
<router-link :to="{ name:'detail', query:{ id:m.id, title:m.title } }">{{m.title}}</router-link>
22.6 路由的params参数
使用占位符声明接收params参数
children:[ { name:"detail", //使用占位符声明接收params参数 path:"detail/:id/:title", component:()=>import('../pages/Detail') } ]
传递参数
<ul> <li v-for="m in messageList" :key="m.id"> <!--跳转路由并携带params参数(to的字符串写法)--> <!--<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>--> <!--跳转路由并携带params参数(to的对象写法)--> <router-link :to="{ name:'detail', params:{ id:m.id, title:m.title } }">{{m.title}}</router-link> </li> </ul>
注意: 使用对象写法不能使用path传路径,必须使用name指定
接收参数
<ul> <li>消息编号: {{ $route.params.id }}</li> <li>消息标题: {{ $route.params.title }}</li> </ul>
22.7 路由的props配置
作用: 让路由组件更方便的收到参数
src/router/index.js
{
name: "detail",
//使用占位符声明接收params参数
path: "detail/:id/:title",
component: () => import('../pages/Detail'),
//第一种写法,props值为对象,该对象中所有的属性都会以props的形式传给Detail组件
// props: {id: "555", title: "XXX"}
//第二种写法,props值为布尔值,如果该对象为真,则吧路由收到的所有params参数通过props传给Detail组件
// props:true
//第三种写法,props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props(route){
return {
id:route.params.id,
title:route.params.title
}
}
}
22.8 <router-link>
的replace属性
- 作用: 控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式: 分别为
push
和replace
,push
是追加历史记录,replace
是替换当前记录.路由跳转时候默认为push
- 如何开启
replace
模式:<router-link replace ......>News<router-link/>
22.9 编程式路由导航
- 作用: 不借助
router-link
实现路由跳转,让路由跳转更加灵活 具体编码
//$router的两个API this.$router.push({ name:"detail", params:{ id:xxx, title:xxx } }) this.$router.replace({ name:"detail", params:{ id:xxx, title:xxx } }) this.$router.forward();//前进 this.$router.back();//后退 this.$router.go(2)//正数前进,负数后退
22.10 缓存路由组件
作用: 缓存路由组件后,组件将不被销毁
<!--缓存路由组件,include指定要缓存的组件名称,不指定则将缓存所有router-view标签渲染的组件(指定单个)-->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
<!--缓存路由组件,include指定要缓存的组件名称(指定多个)-->
<keep-alive :include="['News','Message']">
<router-view></router-view>
</keep-alive>
22.11 两个新的生命周期钩子
- 作用: 路由组件所独有的两个钩子,用于捕获路由组件的激活状态
具体名字:
activated
路由组件被激活时触发deactivated
路由组件失活是触发
22.12 路由守卫
- 作用: 对路由进行权限控制
- 分类: 全局守卫, 独享守卫, 组件内守卫
全局守卫
//引入VueRouter import VueRouter from 'vue-router' //创建router实例对象并暴露 const router = new VueRouter({ //管理一组一组的路由规则 routes: [ { path:"/", redirect:"/login", meta:{title:"登录"} }, { name:"login", path:"/login", meta:{title:"登录"}, component:()=>import('../pages/Login') }, { name: "home", //导航路径 path: "/home", meta:{title:"主页"}, component: () => import('../pages/Home'), children: [ { name: "news", path: "news", //需要权限查看 meta:{isAuth:true,title:"新闻"}, component: () => import('../pages/News') }, { name: 'message', path: "message", //需要权限查看 meta:{isAuth:true,title:"消息"}, component: () => import('../pages/Message'), children: [ { name: "detail", //使用占位符声明接收params参数 path: "detail/:id/:title", meta:{title:"详情"}, component: () => import('../pages/Detail'), //第一种写法,props值为对象,该对象中所有的属性都会以props的形式传给Detail组件 // props: {id: "555", title: "XXX"} //第二种写法,props值为布尔值,如果该对象为真,则吧路由收到的所有params参数通过props传给Detail组件 // props:true //第三种写法,props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件 props(route) { return { id: route.params.id, title: route.params.title } } } ] } ] }, { path: "/about", meta:{title:"关于"}, component: () => import('../pages/About') } ] }) //全局前置路由守卫---初始化的时候被调用,每次路由切换之前被调用 router.beforeEach((to, from, next)=>{ //判断当前路由是否需要鉴权 if(to.meta.isAuth){ //权限控制的具体规则 if(localStorage.getItem('name')==='yiyu'){ //放行 next() }else{ alert("姓名不对,无权限查看") next("/login") } }else{ next() } }) //全局后置路由守卫---初始化的时候被调用,每次路由切换之后被调用 router.afterEach((to, from)=>{ //修改网页的title document.title=to.meta.title }) export default router
22.13 独享守卫
beforeEnter(to,form,next) {
if (to.meta.isAuth) {
//权限控制的具体规则
if (localStorage.getItem('name') === 'yiyu') {
//放行
next()
} else {
alert("姓名不对,无权限查看")
next("/login")
}
} else {
next()
}
}
22.14 组件内守卫
<template>
<h2>我是About中的内容</h2>
</template>
<script>
export default {
name: "About",
//进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next) {
console.log("About---beforeRouteEnter")
if (to.meta.isAuth) {
//权限控制的具体规则
if (localStorage.getItem('name') === 'yiyu') {
//放行
next()
} else {
alert("姓名不对,无权限查看")
next("/login")
}
} else {
next()
}
},
//进入守卫,通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next){
console.log("About---beforeRouteLeave")
next()
}
}
</script>
<style scoped>
</style>
22.15 路由器的两种工作模式
- 对于一个url来说,什么是hash值?----#及其后面的内容就是hash值
- hash值不会包含在HTTP请求中,即: hash值不会带给服务器
hash模式:
- 地址中永远带着#号,不美观
- 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
- 兼容性好
history模式
- 地址干净,美观
- 兼容性和hash模式相比略差
- 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题changeOrigin