vue3之router路由
路由
1、对路由的理解
2、基本使用
安装路由器扩展包
npm i vue-router
创建组件:
Home.vue
<template>
<div class="home">
<img src="https://oss.fmy90.cn/fmy/public/4db8dec4d2eb31b8b0456cb42a907941.png" alt="">
</div>
</template>
<script setup lang="ts" name="Home">
</script>
<style scoped>
.home {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
</style>
News.vue
<template>
<div class="news">
<ul>
<li><a href="#">新闻001</a></li>
<li><a href="#">新闻002</a></li>
<li><a href="#">新闻003</a></li>
<li><a href="#">新闻004</a></li>
</ul>
</div>
</template>
<script setup lang="ts" name="News">
</script>
<style scoped>
/* 新闻 */
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
height: 100%;
}
.news ul {
margin-top: 30px;
list-style: none;
padding-left: 10px;
}
.news li>a {
font-size: 18px;
line-height: 40px;
text-decoration: none;
color: #64967E;
text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
width: 70%;
height: 90%;
border: 1px solid;
margin-top: 20px;
border-radius: 10px;
}
</style>
About.vue
<template>
<div class="about">
<h2>大家好,欢迎来到新世界</h2>
</div>
</template>
<script setup lang="ts" name="About">
</script>
<style scoped>
.about {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
color: rgb(85, 84, 84);
font-size: 18px;
}
</style>
定义路由:
src/router/index.ts
// 创建路由器,并暴露出去
// 第一步:引入
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;
使用路由器:
src/main.ts
// 引入 createApp 用于创建应用
import { createApp } from 'vue'
// 引入 App 根组件
import App from './App.vue'
// 引入路由器
import router from './router'
// 创建一个应用
const app = createApp(App)
// 使用路由器
app.use(router)
// 挂载整个应用到 app 容器中
app.mount('#app')
渲染组件:
src/App.vue
<template>
<div class="app">
<h2>Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<!-- vue-router 不使用 a 标签跳转,需使用 RouterLink -->
<!-- <a href="#">首页</a>
<a href="#">新闻</a>
<a href="#">关于</a> -->
<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></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="App">
import { RouterView, RouterLink } from 'vue-router';
</script>
<style scoped>
.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
文件夹。通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
3、路由器工作模式
3.1 history
模式
优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。
示例代码:
const router = createRouter({
history:createWebHistory(), // history模式
})
3.2 hash
模式
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。
示例代码:
const router = createRouter({
history:createWebHashHistory(), // hash模式
})
4、to 的两种写法
<!-- 第一种:to 的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>
<!-- 第二种:to 的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">主页</router-link>
5、命名路由
作用:可以简化路由跳转及传参
路由规则命名:
routes:[
{
name:'zhuye',
path:'/home',
component:Home
},
{
name:'xinwen',
path:'/news',
component:News,
},
{
name:'guanyu',
path:'/about',
component:About
}
]
跳转路由:
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/news">跳转</router-link>
<!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{name:'guanyu'}">跳转</router-link>
6、嵌套路由
1、编写 News
的子路由:Detail.vue
src/component/Detail.vue
<template>
<ul class="news-list">
<li>编号:xxx</li>
<li>标题:xxx</li>
<li>内容:xxx</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list>li {
line-height: 30px;
}
</style>
2、配置路由规则,使用 children
配置项
src/router/index.ts
// 创建路由器,并暴露出去
// 第一步:引入
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'
// 第二步:创建路由器
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/home",
component: Home
},
{
path: "/news",
component: News,
children: [
{
name: "xiangqing",
path: "detail",
component: Detail
}
]
},
{
path: "/about",
component: About
}
]
})
export default router;
3、 设置页面跳转地址
src/component/News.vue
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 需要指定完整跳转地址 -->
<RouterLink to="/news/detail" active-class="active">{{ item.title }}</RouterLink>
<!-- 或 -->
<!-- <router-link :to="{ path: '/news/detail' }">{{ item.title }}</router-link> -->
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink } from 'vue-router';
const newsList = reactive([
{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },
{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },
{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },
{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])
</script>
<style scoped>
/* 新闻 */
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
height: 100%;
}
.news ul {
margin-top: 30px;
list-style: none;
padding-left: 10px;
}
.news li>a {
font-size: 18px;
line-height: 40px;
text-decoration: none;
color: #64967E;
text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
width: 70%;
height: 90%;
border: 1px solid;
margin-top: 20px;
border-radius: 10px;
}
</style>
7、路由传参
7.1 query 参数
1.传递参数
<!-- 跳转并携带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>
2.接收参数
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query)
7.2 params 传参
传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。传递
params
参数时,需要提前在规则中占位。
- 路由站位
{
path: "/news",
component: News,
children: [
{
name: "xiangqing",
path: "detail/:id/:title/:content?", // :id 站位,"?" 代表可选
component: Detail
}
]
}
- 发送参数 News.vue
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 跳转并携带params参数(to的字符串写法) -->
<!-- <RouterLink :to="`/news/detail/${item.id}/${item.title}/${item.content}`">{{ item.title }}</RouterLink> -->
<!-- 跳转并携带 params 参数(to的对象写法) -->
<RouterLink :to="{
name: 'xiangqing', // 只能用路由的 name 跳转
params: {
id: item.id,
title: item.title,
content: item.title
}
}">
{{ item.title }}
</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink } from 'vue-router';
const newsList = reactive([
{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },
{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },
{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },
{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])
</script>
<style scoped>
/* 新闻 */
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
height: 100%;
}
.news ul {
margin-top: 30px;
list-style: none;
padding-left: 10px;
}
.news li>a {
font-size: 18px;
line-height: 40px;
text-decoration: none;
color: #64967E;
text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
width: 70%;
height: 90%;
border: 1px solid;
margin-top: 20px;
border-radius: 10px;
}
</style>
- 接收参数 Detail.vue
<template>
<ul class="news-list">
<li>编号:{{ params.id }}</li>
<li>标题:{{ params.title }}</li>
<li>内容:{{ params.content }}</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
import { useRoute } from 'vue-router'
import { toRefs } from 'vue';
const route = useRoute()
let { params } = toRefs(route)
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list>li {
line-height: 30px;
}
</style>
8、路由的 props 配置
作用:让路由组件更方便的收到参数(可以将路由参数作为 props
传给组件)
- 路由开启 prop 传参
// 创建路由器,并暴露出去
// 第一步:引入
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'
// 第二步:创建路由器
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/home",
component: Home
},
{
path: "/news",
component: News,
children: [
{
name: "xiangqing",
path: "detail/:id/:title/:content?",
component: Detail,
// 写法1:props 的布尔值写法,作用:将路由接收到的所有 params 参数,作为 props 传给 Detail 组件。Detail 中可以使用 defineProp 方法接收参数
props: true
// 写法2:props 的函数写法,作用:把返回的对象中每一组 key-value 作为 props 传给 Detail 组件。
// props(route) {
// return route.query
// }
// 写法3:props 的对象写法,作用:把对象中的每一组 key-value 作为 props 传给 Detail 组件
// props:{a:1,b:2,c:3}
}
]
},
{
path: "/about",
component: About
}
]
})
export default router;
2.接受参数,Detail.vue
<template>
<ul class="news-list">
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
// 组件接受参数
defineProps(['id', 'title', 'content'])
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list>li {
line-height: 30px;
}
</style>
9、replace 属性
-
作用:控制路由跳转时操作浏览器历史记录的模式。
-
浏览器的历史记录有两种写入方式:分别为
push
和replace
:
push
是追加历史记录(默认值)。replace
是替换当前记录,无法操作后退
- 开启
replace
模式:
<RouterLink replace >News</RouterLink>
10、编程式导航
代码示例:
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<button @click="showDetail(`${item.id}`)">查看详情</button>
<!-- 跳转并携带params参数(to的字符串写法) -->
<!-- <RouterLink :to="`/news/detail/${item.id}/${item.title}/${item.content}`">{{ item.title }}</RouterLink> -->
<!-- 跳转并携带params参数(to的对象写法) -->
<RouterLink :to="{
name: 'xiangqing', // 只能用 name 跳转
params: {
id: item.id,
title: item.title,
content: item.title
}
}">
{{ item.title }}
</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink, useRouter } from 'vue-router';
interface newsInter {
id: string,
title: string,
content: string
}
const newsList = reactive<newsInter[]>([
{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },
{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },
{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },
{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])
let router = useRouter()
function showDetail(id: string) {
const news = newsList.find(item => item.id == id) as newsInter
// to 如何写,push 就可以怎样写
router.push({
name: 'xiangqing', // 只能用 name 跳转
params: {
id: news.id,
title: news.title,
content: news.title
}
})
}
</script>
<style scoped>
/* 新闻 */
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
height: 100%;
}
.news ul {
margin-top: 30px;
list-style: none;
padding-left: 10px;
}
.news li>a {
font-size: 18px;
line-height: 40px;
text-decoration: none;
color: #64967E;
text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
width: 70%;
height: 90%;
border: 1px solid;
margin-top: 20px;
border-radius: 10px;
}
button {
margin-right: 10px;
}
</style>
12、重定向
-
作用:将特定的路径,重新定向到已有路由。
-
路由文件,具体编码:
{ path:'/', redirect:'/about' }