vue3路由
对路由的理解

基本切换效果
Vue3
中要使用vue-router
的最新版本,目前是4
版本。路由配置文件代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
// 创建路由器
const router = createRouter({
history:createWebHistory(),// 路由器工作模式:hash模式/history模式
routes:[
{
path:'/home',
component:Home
},
{
path:'/news',
component:News
},
{
path:'/about',
component:About
}
]
})
export default router
main.ts
代码如下:1
2
3
4
5
6// 引入路由器
import router from './router/index'
const app = createApp(App) // 创建一个应用
app.use(router) // 使用路由器
app.mount('#app') // 挂载整个应用到app容器中
App.vue
代码如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<template>
<div class="app">
<h2 class="title">Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/home" active-class="active">首页</RouterLink>
<RouterLink to="/news" active-class="active">新闻</RouterLink>
<RouterLink to="/about" active-class="active">关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="App">
import {RouterLink,RouterView} from 'vue-router'
</script>
两个注意点
路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
路由器工作模式
一般,后台管理项目,不需要考虑seo,直接用hash模式
前台项目,to C的,直接给客户用的,用history模式
history
模式
优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。
1
2
3
4 const router = createRouter({
history:createWebHistory(), //history模式
/******/
})
hash
模式
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。
1
2
3
4 const router = createRouter({
history:createWebHashHistory(), //hash模式
/******/
})
to的两种写法
字符串形式 和 对象形式
1 | <!-- 第一种:to的字符串写法 --> |
大部分项目,不是这么写路由的,而是直接 遍历的动态路由,这个时候对象尤其重要的
命名路由
作用:可以简化路由跳转及传参(后面就讲)。
给路由规则命名:
1 | routes:[ |
跳转路由:
1 | <!--简化前:需要写完整的路径(to的字符串写法) --> |
嵌套路由
编写
News
的子路由:Detail.vue
配置路由规则,使用
children
配置项:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28const router = createRouter({
history:createWebHistory(),
routes:[
{
name:'zhuye',
path:'/home',
component:Home
},
{
name:'xinwen',
path:'/news',
component:News,
children:[
{
name:'xiang',
path:'detail',
component:Detail
}
]
},
{
name:'guanyu',
path:'/about',
component:About
}
]
})
export default router跳转路由(记得要加完整路径):
1
2
3<router-link to="/news/detail">xxxx</router-link>
<!-- 或 -->
<router-link :to="{path:'/news/detail'}">xxxx</router-link>记得去
Home
组件中预留一个<router-view>
1
2
3
4
5
6
7
8
9
10
11
12<template>
<div class="news">
<nav class="news-list">
<RouterLink v-for="news in newsList" :key="news.id" :to="{path:'/news/detail'}">
{{news.name}}
</RouterLink>
</nav>
<div class="news-detail">
<RouterView/>
</div>
</div>
</template>
路由传参 / 动态路由
query参数
传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<!-- 跳转并携带query参数(to的字符串写法) -->
<router-link to="/news/detail?a=1&b=2&content=欢迎你">
跳转
</router-link>
<!-- 跳转并携带query参数(to的对象写法) -->
<RouterLink
:to="{
//name:'xiang', //用name也可以跳转
path:'/news/detail',
query:{
id:news.id,
title:news.title,
content:news.content
}
}"
>
{{news.title}}
</RouterLink>接收参数:
1
2
3
4import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query参数
console.log(route.query)
params参数
用这种方式传参会被同事骂?因为它的字符串写法可读性很差?XDD
不过对象写法和query参数也没大差吧?而且开启路由传参也比较方便,为什么呢?
不过需要占位,这里也比query要麻烦,而且如果是可以不传的参数还要加?号
传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<!-- 跳转并携带params参数(to的字符串写法) -->
<RouterLink :to="`/news/detail/001/新闻001/内容001`">{{news.title}}</RouterLink>
<!-- 跳转并携带params参数(to的对象写法) -->
<RouterLink
:to="{
name:'xiang', //用name跳转,不能用path,会报错
params:{
id:news.id,
title:news.title,
content:news.title
}
}"
>
{{news.title}}
</RouterLink>接收参数:
1
2
3
4import {useRoute} from 'vue-router'
const route = useRoute()
// 打印params参数
console.log(route.params)
- 需要提前在路由规则占位
1
2
3
4
5
6
7{
path:'/news',
component: News,
children:[
{name:'xiang',path:'detail/:id/:title/:content',component: Detail}
]
} - 如果是可传可不传的参数,需要在规则中加?,否则会报错
1
2
3
4// content 可不传
children:[
{name:'xiang',path:'detail/:id/:title/:content?',component: Detail}
]
备注1:传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。备注2:传递
params
参数时,需要提前在规则中占位。
路由的props配置
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件)
写法:params参数用 布尔值写法; query参数用 函数写法
一般组件是直接写标签的,可以直接传递props
路由组件(这里是Detail)都没有机会写标签,所以通过这种方式来传props
1 | { |
replace属性
作用:控制路由跳转时操作浏览器历史记录的模式。
浏览器的历史记录有两种写入方式:分别为
push
和replace
:push
是追加历史记录(默认值)。replace
是替换当前记录。(登陆页面应该会用这个)
开启
replace
模式:1
<RouterLink replace>News</RouterLink>
声明式导航&编程式导航
编程式路由导航:脱离<RouterLink>
实现路由跳转 (开发常用)
路由组件的两个重要的属性:$route
和$router
变成了两个hooks
声明式 | 编程式 | |
---|---|---|
导航到不同的位置 | <router-link :to="..."> |
router.push(...) |
替换当前位置 | <router-link :to="..." replace> |
router.replace(...) |
横跨历史 | router.go(n) |
router.go(n)
:横跨历史。采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于window.history.go(n)
。n = 1
时,等同于:router.forward()
n = -1
时,等同于:router.back()
router.push
、router.replace
和router.go
是window.history.pushState
、window.history.replaceState
和window.history.go
的翻版,它们确实模仿了window.history
的 API。
值得一提的是,无论在创建路由器实例时传递什么 history 配置(history模式,和hash模式 的路由器工作模式),Vue Router 的导航方法 (push、replace、go) 都能始终正常工作。
应用场景:
- 符合某些条件才跳转,不是说一点就跳转
到了10点整,自动跳到秒杀路由;只有登陆成功,自动跳转到个人中心
- 鼠标滑过一个东西跳转(不点)
- 还有手机摇一摇跳转
1 | import {useRoute,useRouter} from 'vue-router' |
点击button按钮进行路由跳转:
1 | <template> |
在vue2中,编程式路由导航,如果重复跳转是报错的,但是vue3里面不会报错
重定向
作用:将特定的路径,重新定向到已有路由。
- 具体编码:
1 | { |
路由进阶
导航守卫、路由元信息、路由懒加载、路由故障等等
参考官方文档
导航守卫
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。
- 全局前置守卫
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve(解析) 完之前一直处于等待中。- 参数:
- to: 即将要进入的目标
- from: 当前导航正要离开的路由
新版Vue Router移除了next参数,但仍支持使用,因为其是常见的错误来源
确保 next 在任何给定的导航守卫中都被严格调用一次,否则钩子永远都不会被解析或报错。
- 返回值:
- false:取消导航,如果浏览器的 URL 改变了,URL 地址会重置到 from 路由对应的地址。
- 一个路由地址:如同调用 router.push(),且可以传入诸如 replace: true 或 name: ‘home’ 之类的选项。
它会中断当前的导航,同时用相同的 from 创建一个新导航。 - 如果什么都没有,undefined 或返回 true,则导航是有效的,并调用下一个导航守卫
即:
return true 或 undefined(没有返回值默认 为un) ,正常跳转
return false,阻止跳转
return 字符串 或 对象 (就和router.push()传参一样,也即使和to传参一样)
- 参数:
1 | // router/index.ts |
全局前置守卫是最常用的导航守卫,其余还有:全局解析守卫、全局后置钩子、路由独享的守卫、组件内的守卫等,具体使用查看官方文档 - 导航守卫
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫(2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫(2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。