路由
简单路由案例:
在router文件夹下的index.ts文件中:
import {createRouter,createWebHistory} from 'vue-router'
import Car from '@/components/Car.vue'
import Person from '@/components/learning/Person.vue'
import Water from '@/components/learning/Water.vue'
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
path:'/home',
component:Car
},
{
path:'/news',
component:Person
},
{
path:'/about',
component:Water
}
]
})
export default router
配置路由规则,createWebHistory是指定路由的工作模式,routes中的每个元素都是一个配置好的路由,其中path是路由的路径,component是该路由对应的组件
main.ts:
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
挂载app组件之前,要让其配置上路由,使用.use(router)
app.vue:
其中RouterLink标签是用于定位路由的,to就是指定按下该dom后路径会跳向哪个,active-class是指定当为当前路由时,该dom会应用上该class,可以用于指定路由激活时的样式
RouterView就是路由指定的组件的展示区,展示当前路由对应的那个component组件
<script setup lang="ts">
import router from './router'
import { RouterView,RouterLink} from 'vue-router';
</script>
<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>
<style scoped>
/* App */
.title {
text-align: center;
word-spacing: 5px;
margin: 30px 0;
height: 70px;
line-height: 70px;
background-image: linear-gradient(45deg, gray, white);
border-radius: 10px;
box-shadow: 0 0 2px;
font-size: 30px;
}
.navigate {
display: flex;
justify-content: space-around;
margin: 0 100px;
}
.navigate a {
display: block;
text-align: center;
width: 90px;
height: 40px;
line-height: 40px;
border-radius: 10px;
background-color: gray;
text-decoration: none;
color: white;
font-size: 18px;
letter-spacing: 5px;
}
.navigate a.active {
background-color: #64967E;
color: #ffc268;
font-weight: 900;
text-shadow: 0 0 1px black;
font-family: 微软雅黑;
}
.main-content {
margin: 0 auto;
margin-top: 30px;
border-radius: 10px;
width: 90%;
height: 400px;
border: 1px solid;
}
</style>
注意点
- 路由组件通常存放在pages或views文件夹,一般组件通常存放在components文件夹。
- 路由组件,靠路由的规则渲染出来的组件,即放在routes的元素的component配置项中的组件
- 通过点击导航,消失后的组件默认是被卸载掉的,需要的时候再加载
to的第二种写法
to属性里面可以直接写路径,也可以写作一个对象的写法:
<RouterLink :to="{path:'/about'}" active-class="active">关于</RouterLink>
命名路由
给路由命名在routes的路由元素中加一个配置项name,指定名称
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
name:'ergouHome',
path:'/home',
component:Car
}
]
})
然后to的第二种写法对象写法中,就可以指定这个name去指定路由
<RouterLink :to="{name:'ergouHome'}" active-class="active">首页</RouterLink>
路由器工作模式
-
history模式:
-
优点:url更加美观,不带有#,更接近传统的网站url
-
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误
-
使用方式,导入createWebHistory,在createRouter中加入:
const router = createRouter({ history:createWebHistory(),//history模式 routes:[ //…………………… ] })
-
-
hash模式
-
优点:兼容性好,因为不需要服务器端进行处理路径
-
缺点:url带有#不美观,且在seo优化方面相对较差
-
使用:
const router = createRouter({ history:createWebHashHistory(),//hash模式 routes:[ //…………………… ] })
-
嵌套路由
路由的嵌套即在路由组件中继续使用其他路由组件,层层嵌套
在router的index.ts中,要在要配置嵌套路由的路由配置中加上children配置项(数组),其中的元素就是指定一个一个嵌套的子路由组件。子路由组件中的path前面不要加”/”,例:
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
path:'/news',
component:News,
children:[
{
path:'detail',
component:Detail
}
]
}
]
})
在父路由组件中,加上RouterView标签,并配置好RouterLink标签(其中的to要写完整的路径,比如上方的要展示Detail组件,path就要写作/news/detail)
<template>
<div class="news">
<ul>
<li v-for="news in newList" :key="news.id">
<RouterLink to="/news/detail">{{ news.title }}</RouterLink>
</li>
</ul>
<div class="newsContent">
<RouterView></RouterView>
</div>
</div>
</template>
路由传参之query参数
用query参数可以添加或者获取路径上的param参数列表,即路径上的?后面的kv信息。以达到路由传参的
添加:添加一般由父路由组件指定参数信息:有两种写法:
-
第一种:字符串中的参数值占位
<ul> <li v-for="news in newList" :key="news.id"> <!-- 第一种写法 --> <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}`">{{ news.title }}</RouterLink> </li> </ul>
但是第一种方式不方便,且观感上不美观。建议使用第二种方式
-
第二种,使用对象式写法
<ul> <li v-for="news in newList" :key="news.id"> <!-- 第二种写法:将to写作对象的形式 --> <RouterLink :to="{ // path:'/news/detail', name:'detail', query:{ id:news.id, title:news.title, content:news.content } }">{{ news.title }}</RouterLink> </li> </ul>
获取:子路由组件获取query的参数值
<template>
<ul class="news-list">
<li>编号:{{ route.query.id }}</li>
<li>标题:{{ route.query.title }}</li>
<li>内容:{{ route.query.content }}</li>
</ul>
</template>
<script lang="ts" name="About" setup>
import { useRoute } from 'vue-router';
let route = useRoute()
</script>
用useRoute就可以获取到地址上的各个参数的参数值,这些参数值都是存于query参数中,所以获取要使用 route.query.参数名。
路由传参之params参数
params参数是将参数值直接以路径的形式存在路径当中
要让路由不会将路径上的值视为真正的路径,就要在router中的index.ts中的路由配置中指定好参数名:
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
name:'about',
path:'/about',
component:News2,
children:[
{
path:'detail2/:id/:title/:content',
name:'detail2',
component:Detail2
}
]
}
]
})
添加参数:
<ul>
<li v-for="news in newList" :key="news.id">
<!-- 第一种写法 -->
<!-- <RouterLink :to="`/about/detail2/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink :to="{
name:'detail2',//此时只能使用指定name来指定路由的写法
params:{
id:news.id, //此处的名称要根据路由中指定的参数名来
title:news.title,
content:news.content
}
}">{{ news.title }}</RouterLink>
</li>
</ul>
但是这种方式不能传入数组类型的数据
如果想让参数可传可不传,在参数名后加上一个?
获取参数:
<template>
<ul class="news-list">
<li>编号:{{ route.params.id }}</li>
<li>标题:{{ route.params.title }}</li>
<li>内容:{{ route.params.content }}</li>
</ul>
</template>
<script lang="ts" name="About" setup>
import { useRoute } from 'vue-router';
let route = useRoute()
</script>
路由传参之路由的props配置
- 第一种写法:将所有的params参数信息多一份转换为给子路由组件的props配置项的参数。(只能用于params参数)
在子路由组件的路由配置中加上props配置项,直接让其值为true。
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
name:'about',
path:'/about',
component:News2,
children:[
{
path:'detail2/:id/:title/:content',
name:'detail2',
component:Detail2,
props:true
}
]
}
]
})
如此Detail2组件就会多三个props参数id、title、content。
<template>
<ul class="news-list">
<li>编号:{{ route.params.id }}</li>
<li>标题:{{ route.params.title }}</li>
<li>内容:{{ route.params.content }}</li>
<hr>
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script lang="ts" name="About" setup>
import { useRoute } from 'vue-router';
let route = useRoute()
defineProps(['id','title','content'])
</script>
<style>
.news-list{
list-style: none;
padding-left: 20px;
}
.news-list>li{
line-height: 30px;
}
</style>
- 第二种写法:函数式写法,可以获取route并使用,也就是那个useRoute()的返回值
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
name:'news',
path:'/news',
component:News,
children:[
{
name:'detail',
path:'detail',
component:Detail,
props(route){
return {//也可以直接return route.query
id:route.query.id,
title:route.query.title,
content:route.query.content
}
}
}
]
}
]
})
这里的route参数接收的就是useRoute()的返回值的那个route,因为第一种写法不能使用在query参数的使用上,但是第二种写法都可以适用,也可以自己return想要的props参数。return返回的参数就会变成给子路由组件的props参数。
- 第三种写法:对象式写法,可以自己决定将什么作为props参数给路由组件。
props:{
a:100,
b:200,
c:'abc'
}
但是这种写法写死了,不灵活,建议使用第一种或者第二种。
replace属性
<RouterLink :to="…… ……" replace>…… ……</RouterLink>
push模式就是将浏览器历史记录以栈的形式存储,新点开的页面状态加到栈顶,replace模式就是将新点开的页面状态替换掉当前页面状态到栈顶。
要让某个路由是replace模式的,在对应的RouterLink标签上加上replace属性即可。
编程式导航
编程式路由导航就是脱离<RouterLink>实现路由跳转。
要实现这种方式,使用useRouter(注意是useRouter,不是useRoute),例:
<template>
<div class="home">
<img src="<http://www.atguigu.com/images/index_new/logo.png>">
</div>
</template>
<script lang="ts" setup>
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter()//注意,不是useRoute,是useRouter
onMounted(()=>{
setTimeout(()=>{
router.push('/news')
},5000)
})
</script>
调用router的push函数,传入要跳转的路由,就可以实现不使用RouterLink的方式来跳转路由。
push函数中还可以写做对象的写法,说白了就是,to中怎么写,push的参数中就怎么写。
<template>
<div class="news">
<ul>
<li v-for="news in newList" :key="news.id">
<!-- 第一种写法 -->
<!-- <RouterLink :to="`/about/detail2/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink :to="{
name:'detail2',//此时只能使用指定name来指定路由的写法
params:{
id:news.id, //此处的名称要根据路由中指定的参数名来
title:news.title,
content:news.content
}
}">{{ news.title }}</RouterLink>
<button @click="showNewsDetail(news.id,news.title,news.content)">查看新闻</button>
</li>
</ul>
<div class="newsContent">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
import { RouterView ,RouterLink,useRouter} from 'vue-router';
const newList = reactive([
{id:'new01',title:'很好的抗癌食物',content:'西兰花'},
{id:'new02',title:'如何一夜暴富',content:'做梦'},
{id:'new03',title:'如何赚大钱',content:'学it'},
{id:'new04',title:'好消息',content:'放假了'}
])
const router = useRouter()
function showNewsDetail(id:string,title:string,content:string){
router.push({
name:'detail2',
params:{
id:id,
title:title,
content:content
}
})
}
</script>
如果想要使用replace模式,将push换成replace函数就行,写法一样。
重定向
在route包下的index.ts中,要加上重定向,加上一个路由元素,使用redirect属性,例:
const router = createRouter({
history:createWebHistory(),//路由器的工作模式
routes:[
{
name:'ergouHome',
path:'/home',
component:Home
},
{
name:'news',
path:'/news',
component:News,
children:[
{
name:'detail',
path:'detail',
component:Detail,
props(route){
return {
id:route.query.id,
title:route.query.title,
content:route.query.content
}
}
}
]
},
{
name:'about',
path:'/about',
component:News2,
children:[
{
path:'detail2/:id/:title/:content',
name:'detail2',
component:Detail2,
props:true
}
]
},
{ //重定向
path:'/',
redirect:'/home'
}
]
})
当配置了重定向的时候,当路径为其path的时候,就会跳转到redirect指定的那个路由