路由
路由器检测到路由的变化,路径变化,对应的组件也变化
基本使用
想使用路由:
① 确定导航区、展示区
② 请来路由器 npm i vue-router
③ 指定路由的具体规则(什么路径、对应着什么组件)
在 src 底下 创建一个文件夹 router/index.ts (vue3中是ts不是js)
④ 形成一个一个的 .vue 文件
- 配置路由 src/router/index.ts
// 创建一个路由器 并暴露出去
// 第一步 引入 createRouter
import {createRouter,createWebHistory} from 'vue-router'
// 引入一个一个可能要呈现的组件
import Home from '@/components/Home.vue';
import News from '@/components/News.vue';
import About from '@/components/About.vue';
// 第二步 创建路由器
const router = createRouter({
history:createWebHistory(), // 路由器的工作模式
routes: [
{
path: '/home',
component: Home,
},
{
path: '/news',
component: News,
},
{
path: '/about',
component: About,
}
]
})
export default router
- main.ts
import {createApp} from 'vue'
import App from './App.vue'
// 引入路由器
import router from './router'
// createApp(App).mount('#app')
// 创建应用
const app = createApp(App)
// 使用路由器
app.use(router)
// 挂载
app.mount('#app')
- app.vue :RouterLink、RouterView
<template>
<div class="app">
<h2 class="title">Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/home" active-class="xiaozhupeiqi">首页</RouterLink>
<RouterLink to="/news" active-class="xiaozhupeiqi">新闻</RouterLink>
<RouterLink to="/about" active-class="xiaozhupeiqi">关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="App">
</script>
两个注意点
-
路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。 -
通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
通过生命周期函数验证 onMounted 、onUnMounted
路由器工作模式
import {createRouter,createWebHistory,createWebHashHistory} from ‘vue-router’
-
history
模式优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。const router = createRouter({ history:createWebHistory(), //history模式 /******/ })
-
hash
模式优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。const router = createRouter({ history:createWebHashHistory(), //hash模式 /******/ })
to的两种写法
<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>
<!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
对象写法,to的前面必须加一个冒号,表示绑定,实际路径为 双引号内部的对象。如果不写绑定,就是字符串
【命名路由】
作用:可以简化路由跳转及传参(后面就讲)。
给路由规则命名:
routes:[
{
name:'zhuye', // 给路由命名
path:'/home',
component:Home
},
{
name:'xinwen', // 给路由命名
path:'/news',
component:News,
},
{
name:'guanyu', // 给路由命名
path:'/about',
component:About
}
]
跳转路由:
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/about">跳转</router-link>
<!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{name:'guanyu'}">跳转</router-link>
【嵌套路由】
1、编写News
的子路由:Detail.vue
2、配置路由规则,使用children
配置项:
children配置项里面的路径 path 不加斜杠
const 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
3、跳转路由(记得要加完整路径):
<router-link to="/news/detail">xxxx</router-link>
<!-- 或 -->
<router-link :to="{path:'/news/detail'}">xxxx</router-link>
4、记得去Home
组件中预留一个<router-view>
<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>
路由传参
route 路由:一组对应关系
router 路由器:管理路由
query参数
-
query写法(带问号):/news/detail?id=111&title=haha
-
query参数 有两种写法 是因为 to有两种写法
to的两种写法:
<RouterLink to="/news/detail">
{{ news.title }}
</RouterLink>
<!-- to的对象写法,前面需要加冒号 -->
<RouterLink
:to="{
path: '/news/detail', //或者 name:'xiangqing'
}">
{{ news.title }}
</RouterLink>
-
传递参数
① to的字符串写法:配合模板字符串。to前面加一个冒号,表示它实际上的内容是双引号里面的字符串(模板字符串)
② to的对象写法
<!-- 跳转并携带query参数(to的字符串写法) --> <li v-for="news in newsList" :key="news.id"> <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">{{ news.title }}</RouterLink> </li> <!-- 跳转并携带query参数(to的对象写法) --> <RouterLink :to="{ //name:'xiangqing', //用name也可以跳转 path:'/news/detail', query:{ id:news.id, title:news.title, content:news.content } }" > {{news.title}} </RouterLink>
-
接收参数:
这里 useRoute 是 hooks(usexxx 命名规则)
import {useRoute} from 'vue-router' const route = useRoute() // 打印query参数 console.log(route.query)
如果想解构 route.query,会失去响应式。从一个响应式对象身上解构属性,该属性必定丢失响应式。要使用 toRefs.
正确做法:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query参数
let {query} = toRefs(route)
params参数
哈哈 嘿嘿 呼呼 是参数,但是vue会认为是路由规则。所以需要在路由中配置规则,告诉路由哪部分不算路径。
<RouterLink to="/news/detail/哈哈/嘿嘿/呼呼">{{ news.title }}</RouterLink>
1、配置规则
需要在 /router/index.ts中先配置规则
{
path: '/news',
component: News,
children: [
{
name:'xiangqing',
path: 'detail/:id/:title/:content', //占位
component: Detail
}
]
}
数据content 可传可不传的写法:
path: 'detail/:id/:title/:content?'
表示content内容可传可不传
2、传递参数:
备注1:传递params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。
备注2:传递params
参数时,需要提前在规则中占位。
<li v-for="news in newsList" :key="news.id">
<!-- 字符串写法 -->
<RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink>
<!-- 对象写法 -->
<RouterLink :to="{
name:'xiangqing',
params:{
id: news.id,
title: news.title,
content: news.content
}
}">
{{ news.title }}
</RouterLink>
</li>
3、接收参数:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印params参数
console.log(route.params)
路由规则的props配置
- /router/index.ts
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件)
{
name:'xiang',
path:'detail/:id/:title/:content',
component:Detail,
// props的布尔值写法,作用:把收到了每一组【params参数】,作为props传给Detail组件
// props:true
// props的对象写法,作用:把对象中的每一组key-value作为props传给Detail组件
// props:{a:1,b:2,c:3},
// props的函数写法,作用:把返回的对象中每一组key-value作为props传给Detail组件
props(route){
return route.query
}
}
① 对应props的布尔值写法(把收到了每一组【params参数】,作为props传给Detail组件):
News.vue
<li v-for="news in newsList" :key="news.id">
<!-- 字符串写法 -->
<RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink>
</li>
Detail.vue
<template>
<ul class="news-list">
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script setup lang="ts" name="About">
defineProps(['id','title','content'])
</script>
② 对应props的函数写法
{
name:'xiang',
path:'detail/:id/:title/:content',
component:Detail,
props(route){
return route.query
}
}
Detail.vue
<template>
<ul class="news-list">
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script setup lang="ts" name="About">
defineProps(['id','title','content'])
</script>
之前在父组件Father.vue 中注册使用子组件Son.vue(一般组件),可以直接在父组件内传递参数,<Son a="123">
于是在Son.vue中使用 defineProps接收参数。
但是如果是路由组件,其并不在父组件中注册,而是通过路由切换组件,这是就可以用到 本小节的路由规则的props配置。在路由组件中也用defineProps接收参数。
replace属性
-
作用:控制路由跳转时操作浏览器历史记录的模式。
-
浏览器的历史记录有两种写入方式:分别为
push
和replace
:push
是追加历史记录(默认值)。replace
是替换当前记录。
-
开启
replace
模式:<RouterLink replace .......>News</RouterLink>
编程式导航
之前我们路由跳转的时候,使用的是routerlink和routerview。最终浏览器会把 RouterLink 标签变为认识的 a 标签。但如果我们想要点击按钮跳转,怎么实现?
什么叫编程式路由导航?脱离 routerlink 实现路由跳转。
路由组件的两个重要的属性:$route
和$router
变成了两个hooks
import {useRoute,useRouter} from 'vue-router'
const route = useRoute()
const router = useRouter()
console.log(route.query)
console.log(route.parmas)
console.log(router.push)
console.log(router.replace)
- 示例
import {useRouter} from 'vue-router'
const router = useRouter()
router.push('/news')
这里的 push 写法,和routerlink中的to写法一样,有字符串写法、也有对象写法
router.push({
path: '/news/detail',
query: {
id: news.id,
title:news.title,
content:news.content
}
})
利用接口进行限制
import {useRouter} from 'vue-router'
const router = useRouter()
// 利用接口进行限制
interface NewsInter {
id:string,
title:string,
content:string
}
function showNewsDetail(news:NewsInter) {
router.push({
name: 'xiangqing',
query: {
id: news.id,
title: news.title,
content: news.content
}
})
}
注意,在vue2中,编程式路由导航重复跳转是报错的。vue3中不算错。
- 使用场景
只有满足了某种条件之后,才会跳转路由。比如广告五秒之后跳转页面。
重定向
-
作用:将特定的路径,重新定向到已有路由。
-
具体编码:
{ path:'/', redirect:'/about' }