Vue Router 官方文档
一、路由简介
路由(router)实际上是一种对应关系 —— 一组 key——value 的对应关系,value 可以是 函数 或者 组件 多个路由需要经过路由器的管理
前端中路由的作用:实现单页面(SPA)应用,也即实现网页里展示区(组件)根据导航区的来回切换
多页面应用:可在多个html之间跳转,以此显示不同网页的功能 . 单页面应用:只有一个页面,无法实现页面的跳转。而是通过选择页面中响应功能选项,在页面的特定区域显示响应的不同功能页面。整个切换过程中,页面不发生跳转,页面只进行局部更新。
一个很形象的例子就是,一个页面内的分类导航 - 展示效果
1、vue router是vue的一个插件库,专门用来实现SPA应用
2、SPA应用:
- single page web application,单页面 Web 应用
- 整个应用只有一个完整的页面
- 点击页面中的导航链接不会刷新整个页面,只会做页面的局部更新
- 数据需要通过 AJAX 请求获取
路由分类
1、前端路由:
- value 是
component 组件 ,用于展示页面内容 - 工作流程:当浏览器路径改变时,对应组件显示
2、后端路由:
路由安装
vue2 中使用vue-router3
npm i vue-router@3
vue3 中使用vue-router4
npm i vue-router@4
实际项目开发中,路由组件一般存放在自己创建的名为pages 的文件夹中,以便与其他组件区分
二、路由基本使用
安装路由器并设置路由规则
main.js 中引入并应用
import vueRouter from 'vue-router'
Vue.use(vueRouter)
创建一个新文件夹router ,用于打包路由器 router/index.js
import vueRouter from 'vue-router'
import home from '.../components/home'
import roles from '.../components/roles'
const router = new VueRouter({
routes:[
{
path:'/home',
component:home
},
{
path:'/roles',
component:roles
}
]
})
export default router
main.js 中引入暴露的路由器并添加入 vm
import router from './router'
new Vue({
router:router
})
实现路由切换
使用router 提供的 特殊a标签 <router-link> ,其格式如下
<router-link class="xxx" to="/目标组件或路径">Content</router-link>
<router-link class="list-group-item" active-class="active" to="/roles">Roles</router-link>
使用active-class 可以配置高亮样式
被切走的路由组件会被销毁
指定组件的呈现位置
使用router 提供的特殊标签<router-view> ,换而言之,路由匹配到的组件会被渲染到<router-view> 标签所在的位置
this中的 $router 和 $route
1、$route:每个组件独有的,互不相同,存储每个组件自己的路由信息
2、$router:所有路由组件共享的,整个应用只有一个,可以通过组件的 $router 属性获取
三、命名路由
为路由设置name 配置项,所取的名称为组件的路由名 ,其有以下优点
- 简化路由跳转写法(对多级路由比较明显)
- 没有硬编码的 url
parmas 自动编码解码- 防止开发者在 url 中出现打字错误
- 绕过路径排序
const routes = [
{
path: '/home/:newsPage',
name: 'News',
component: user,
}
]
使用<router-link> 标签中的:to 属性传递一个对象,连接到一个命名路由,当然也可以直接用name 代替path 传入,比如::to="News" ,但不好
使用格式为::to="{ name:xxx }"
<router-link :to="{
name: 'News',
params: { newsPage: 'education' }
}">
News
</router-link>
等同于将对象传入router.push()
router.push({name: 'News', params: { newsPage: 'education' }})
这种情况下,路由将会导航到路径/News/education
四、命名视图
五、嵌套(多级)路由
字面意思,路由组件中嵌套路由组件,类似套娃
子路由组件的路由规则以数组形式存放在父组件的children 配置项的数组中,注意子路由组件的path 不加/
此外,还可以通过name 属性为自路由组件
export default new VueRouter({
route:[
{
path:'/home',
component:Home,
children:[
{
path:'news',
name:'showNews'
component:News,
},
{
path:'videos',
components:Video
}
]
}
]
})
匹配子路由组件,<router-link> 的to="xxx" 中,xxx 为/父组件路径/子组件路径 ,即需要使用子级路由,并带着父级的路径
<router-link class="list-group" active-class="active" to='/home/news'>新闻</router-link>
六、给路由传参
使用query参数
路由从query 取参数,query参数接收一个对象,其中存储需要传递的参数
方法一:to的字符串写法:
参数存入 vm 的data ,然后在 router-link 标签的 to="xxx" 中使用模板字符串 和${xxx} ,将参数xxx 传入。在路径后:?=key1=${value1}&key2=${value2}
${xxx} :解析参数xxx
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id>
<router-link :to="`/home/xxx?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Message',
data() {
return {
messageList:[
{id:'001',title:'番茄'},
{id:'002',title:'哈密瓜'},
{id:'003',title:'火龙果'}
]
}
}
}
</script>
方法二:to的对象写法 —— 使用query 格式:to="{}" 传入两个参数——目标路径path ,query (对象,用于接收给路由传递的参数)
<router-link :to="{
path:'/目标路径',
query:{
id: m.id
title: m.title
}
}">
{{m.title}}
</router-link>
使用params参数
首先在配置路由时必须声明接收params参数 ,格式为:path:'路径/:key1/:key2' ,如下
route:[
{
path:'home/:id/:title',
component:Home
}
]
以下为参数传递
写法一:to的字符串写法 to的字符串写法中,在路径后接/${xxx}/${yyy} 传入参数
<router-link :to="`/home/xxx/${m.id}/${m.title}`">{{m.title}}</router-link>
写法二:to的对象写法 使用params 时,不能传入 path 配置项,必须使用name
<router-link :to="{
name:'/目标路径',
params:{
id: m.id
title: m.title
}
}">
{{m.title}}
</router-link>
接收参数:
$route.params.keyName
props配置项——让路由组件更加方便地接收到参数
作用:解决路由里需要传入众多 key-value 的问题
第一种写法:值为对象 传递props
routes:[
{
path:'/news',
component:Home,
props:{
key1: value1,
id: 001
}
}
]
Home.vue :接收
<script>
export default {
props: ['key1', 'id']
}
</script>
第二种写法:值为布尔值
- 若布尔值为真,则会把该路由组件收到的
所有params参数 ,。一props形式传给对应组件
props:true
第三种写法:值为函数
routes:[
{
path: '/home',
component: Home,
props($route) {
return {
id: $route.query.id,
title: $route.query.title
}
}
props({query}) {
id: query.id,
title: query.title
}
props( {query: {id, title}} ) {
return {id, title}
}
}
]
七、编程式导航 - 可操作历史记录
导航到不同位置
router.push(...) 方法:用于导航到不同的 URL,这种方法回向 history栈 添加一个新记录,所以当用户点击浏览器后退按钮时,会回到之前的 URL,即实现 后退 功能
点击<router-link> 时,后台会调用router.push() 方法,所以点击前者就相当于在后台调用后者
声明式 | 编程式 |
---|
<router-link :to="xxx"> | router.push(xxx) |
:to="xxx" :在<router-link> 中的to 属性前面添加: ,其意义是将to 后引号中的内容作为js 解析
router.push() 接收一个 字符串路径,或是一个描述地址的对象作为参数
router.push('/xxx/name')
router.push({ path:'/xxx/name' })
router.push({ name:'xxx', params:{ username: 'name' } })
router.push({ path:'/xxx', query:{ plan: 'yyy' } })
router.push({ path: '/xxx', hash: '#yyy' })
如果提供了path ,那么params 会被忽略,二者不可以一起使用
router.push 和其他导航方法都会返回一个promise
替换当前位置
声明式 | 编程式 |
---|
<router-link :to="xxx" replace> | router.replace(...) |
作用类似于router.push() ,但他的导航是取代当前条目,不会在history中添加新纪录,故而无法进行回退
这也可以通过给router.push() 的对象参数中设置replace: true 实现
router.replace({ path: '/home' })
router.push({ path: '/home', replace: true })
横跨历史
router.go() 类似于页面的前进或后退多少步,该方法采用一个整数作为参数,表示页面在历史堆栈中前进或后退的步数,正数前进,负数后退
router.go(1)
router.go(-1)
router.go(1000)
八、缓存路由组件
<keep-alive> :包裹需要展示的<router-view> ,相关组件将缓存下来,切换路由组件时路由组件不会被销毁(Destroy)
可以使用其include 属性指定对其中的某些组件缓存,没有被纳入该属性的路由组件在不展示时会被销毁。include 中接收的名字是组件名
component.vue
<router-link to="/home/news">News</router-link>
<router-link to="/home/books">Books</router-link>
<keep-alive include="news">
<router-view></router-view>
</keep-alive>
如果想要缓存多个路由组件,则需要传入数组,格式为::include="['组件1', '组件2']"
<keep-alive :include="['news','books']">
<router-view></router-view>
</keep-alive>
九、两个新生命周期钩子(路由组件独有) —— activated 和 deactiveated
vue的12个生命周期钩子
activated() 激活
路由组件被激活时触发
deactivated() 失活
路由组件失活时触发
十、路由守卫 —— 用户权限相关
如果路由需要设置权限,则可以在需要的路由规则中设置配置项isAuth:true
routes:[
{
path:'/home',
component:Home,
meta:{
isAuth: true,
title: '首页'
}
}
]
全局路由守卫
全局前置路由守卫:
router.beforeEach((to,from,next) => {}) :设置全局前置路由守卫,在初始化时、每一次路由切换前被调用
接收三个参数:to-目标路由 、from-当前路由 、next
router/index.js
router.beforeEach((to,from,next) => {
if(to.meta.isAuth){
if(localStorage.getItem('school') === 'SC1'){
next();
}else{
alert('数据核对未通过,无权限查看!')
}
}else{
next()
}
})
全局后置路由守卫:
router.afterEach((to,from) => {}) :初始化时、每次路由切换后执行。因为已经是切换之后,所以不需要传入 next
可以将对目标路由组件的操作放在这里,只要切换成功,则必定触发全局后置路由守卫的内容。
router/index.js
router.afterEach((to,from) => {
if(to.meta.title){
document.title = to.meta.title
}
})
独享路由守卫
beforeEnter(to,from,next){} :只对某个路由组件自己单独起作用,不影响其他组件
beforeEnter(to,from,next){
if(to.meta.isAuth){
if(localStorage.getItem('school') === 'SC2'){
next()
}else{
alert('您无权查看此内容')
}
}else{
next()
}
}
组件内路由守卫
在 组件vc内 写路由守卫,而不是在路由器配置文件中写。必须通过路由规则进行路由切换才会触发 组件内路由守卫
1、beforeRouterEnter(to,from,next){} :通过路由规则,进入组件时被调用
src/pages/test.vue
beforeRouterEnter(to,from,next){
if(ti.meta.isAuth){
if(localStorage.getItem('xxx') === 'yyy'){
next()
}else{
alert('无权查看')
}
}
}
2、beforeRouterLeave(to,fom,next){} :通过路由规则,离开该组件时被调用
beforeRouterLeave(to,from,next){
next()
}
十一、路由器工作模式 —— hash模式 与 history模式
在路由器文件中可以通过配置项mode 设置工作模式,有 hash模式 和 history模式 两种选择
src/router/index.js
const router = new VueRouter({
mode: 'hash',
routes:[
]
})
hash模式:
1、hash值:在一个 url 中,# 以及它后面的内容就是 hash值 2、hash值 不会被包含到HTTP请求中,它不会被传给服务器 3、特点:
- 兼容性好
- 如果将地址通过第三方手机app分享,但app校验严格,那么地址可能会被标记不合法
- 地址中带着标志性的
#
history模式:
- 兼容性较 hash模式 略差
- 地址无
# - 应用部署上线时需要后端人员支持。解决刷新页面时服务端404的问题
|