4. 路由
4.1. 【对路由的理解】

4.2. 【基本切换效果】
Vue3
中要使用vue-router
的最新版本,截止到2024-02-13日,目前是4
版本(4.2.5)。安装:
sh
npm install vue-router -S
//或者
cnpm install vue-router -S
- 提前定义用于根据路径动态切换的几个组件(此处演示用于介绍html、css、Javascript三个知识点的组件切换)
vue<!-- 1 定义组件模版 --> <template> <div class="com"> 介绍CSS的知识,样式,布局,内置函数,important </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="CssComponent"> import { ref } from 'vue' </script> <!-- 3 定义样式 --> <style scoped> .com{ overflow-y:auto; min-height:300px } </style>
vue<!-- 1 定义组件模版 --> <template> <div class="com"> 介绍HTML的知识1 <br/> 介绍HTML的知识2 <br/> 介绍HTML的知识3 <br/> 介绍HTML的知识4 <br/> 介绍HTML的知识5 <br/> 介绍HTML的知识6 <br/> </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="HTMLComponent"> import { ref } from 'vue' </script> <!-- 3 定义样式 --> <style scoped> .com{ overflow-y:auto; min-height:300px } </style>
vue<!-- 1 定义组件模版 --> <template> <div> 介绍js的知识 </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="JSComponent"> import { ref } from 'vue' </script> <!-- 3 定义样式 --> <style scoped> </style>
- 定义和使用路由,在
src/router/index.ts
中定义路由,在main.js
中使用路由
tsimport {createRouter,createWebHistory} from 'vue-router' import CSS from '@/views/CSS.vue' import HTML from '@/views/HTML.vue' import JavaScript from '@/views/JavaScript.vue' const router = createRouter({ history:createWebHistory(), routes:[ { path:'/html', component:HTML }, { path:'/css', component:CSS }, { path:'/js', component:JavaScript } ] }) export default router
jsimport { createApp } from 'vue' import App from './App.vue' //引入ElementPlus组件库 import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import router from './router/index' const app = createApp(App) //注册全局组件 app.use(ElementPlus) app.use(router) app.mount('#app')
- 在App中使用路由动态渲染不同的组件
查看代码
vue
<template>
<div class="app">
<h2 class="title">Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<span> <RouterLink to="/html" active-class="active" >HTML知识点</RouterLink></span>
<span> <RouterLink to="/css" active-class="active">css知识点</RouterLink></span>
<span> <RouterLink to="/js" active-class="active">JavaScript</RouterLink></span>
</div>
<!-- 展示区 -->
<div class="main-content">
<router-view></router-view>
</div>
</div>
</template>
<script lang="ts" setup name="App">
//可以不用显示的注册组件,在main.js中使用的app.use(router)已经注册全局组件
import { RouterLink, RouterView } from 'vue-router'
</script>
<style scoped>
.app{
width: 800px;
min-height: 500px;
box-shadow: 0 0 10px inset;
padding: 20px;
}
.RouterLink{
line-height: 50px;
}
.navigate{
height: 50px;
line-height: 50px;
background-image: linear-gradient(45deg, rgb(224, 217, 217) 0 33%, rgb(169, 169, 238) 33% 66%, rgb(157, 181, 157) 66% 100%);
display: flex
}
.navigate span{
flex:1;
display: flex;
align-items: center;
justify-content: center;
}
.navigate span a{
text-align: center;
}
.navigate span a.active{
color: red;
}
.navigate span a{
color:rgb(116, 105, 92);
font-weight: 900;
text-decoration: none;
letter-spacing: 2px;
}
.main-content{
width: 100%;
margin: 10px 0;
border:solid 2px grey;
box-shadow: 0 0 5px black;
border-radius: 10px;
}
</style>
实现效果如下:
4.3. 【两个注意点】
路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
4.4.【路由器工作模式】
history
模式优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。jsconst router = createRouter({ history:createWebHistory(), //history模式 /******/ })
hash
模式优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。jsconst router = createRouter({ history:createWebHashHistory(), //hash模式 /******/ })
4.5. 【to的两种写法】
vue
<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link>
<!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
4.6. 【命名路由】
作用:可以简化路由跳转及传参(后面就讲)。
给路由规则命名:
js
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'
import CSS from '@/views/CSS.vue'
import HTML from '@/views/HTML.vue'
import JavaScript from '@/views/JavaScript.vue'
const router = createRouter({
history:createWebHistory(),
// history:createWebHashHistory(),
routes:[
{
path:'/',
redirect:'/html'
},
{
path:'/html',
component:HTML
},
{
name:"ToCSS",
path:'/css',
component:CSS,
},
{
path:'/js',
component:JavaScript,
}
]
})
export default router
跳转路由:
vue
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/css">跳转</router-link>
<!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{name:'ToCSS'}">跳转</router-link>
4.7. 【嵌套路由】
在基本效果图中Javascript章节(组件下)包含多个章节可以采用嵌套路由的方式实现,主要改造如下
- 准备两个组件用于切换
- 修改
Javascript.vue
添加router-link
和router-view
- 修改
src/router/index.ts
添加children嵌套路由
具体代码如下
vue<!-- 1 定义组件模版 --> <template> <div> Javascript的基础语法 </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="JSComponent1"> </script> <!-- 3 定义样式 --> <style scoped> </style>
vue<!-- 1 定义组件模版 --> <template> <div> js的内置对象 </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="JSComponent1"> </script> <!-- 3 定义样式 --> <style scoped> </style>
vue<!-- 1 定义组件模版 --> <template> <div> 介绍js的知识 <div> <div class="left jsblock"> <ol> <li><router-link to="/js/chapter1">第一章节</router-link></li> <li><router-link to="/js/chapter2">第二章节</router-link></li> </ol> </div> <div class="right jsblock"> <router-view></router-view> </div> </div> </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="JSComponent"> import { ref } from 'vue' </script> <!-- 3 定义样式 --> <style scoped> .jsblock { display: inline-block; min-height: 400px; border: solid 1px red; vertical-align:top; } .left { width: 200px; margin-left: 10px } .right { width: 570px; margin-left: 10px; } </style>
tsimport {createRouter,createWebHistory} from 'vue-router' import CSS from '@/views/CSS.vue' import HTML from '@/views/HTML.vue' import JavaScript from '@/views/JavaScript.vue' import JavaScriptChapter1 from '@/views/js/chapter1.vue' import JavaScriptChapter2 from '@/views/js/chapter2.vue' const router = createRouter({ history:createWebHistory(), routes:[ { path:'/html', component:HTML }, { path:'/css', component:CSS }, { path:'/js', component:JavaScript, children:[ { path:'/js/chapter1', component:JavaScriptChapter1 }, { path:'/js/chapter2', component:JavaScriptChapter2 }, ] } ] }) export default router
4.8. 【路由传参】
query参数
传递参数
vue<!-- 1 定义组件模版 --> <template> <div class="com"> 介绍CSS的知识,样式,布局,内置函数,important <div class="comApp"> <ul> <li v-for="chapter in chapters"> <!-- <router-link :to="`/css/detail?id=${chapter.id}&title=${chapter.title}&content=${chapter.content}`"> {{ chapter.title }} </router-link> --> <!-- <router-link :to="{ path:'/css/detail', query:{ ...chapter } }"> {{ chapter.title }} </router-link> --> <router-link :to="{ name:'CssDeatail', query:{ ...chapter, } }"> {{ chapter.title }} </router-link> </li> </ul> <div> <router-view></router-view> </div> </div> </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="CssComponent"> import { onUnmounted, onMounted, ref, reactive } from 'vue' let chapters = reactive([ { id: "asdfsadf001", title: '布局', content: '使用position属性进行布局' }, { id: "asdfsadf002", title: '内置函数', content: '内置了calc,xxx等函数' }, { id: "asdfsadf003", title: '属性(宽高)', content: '宽高的取值有 px cm vh vw等 ' }, ]) onMounted(() => { console.log('CSS挂载') }) onUnmounted(() => { console.log('CSS卸载') }) </script> <!-- 3 定义样式 --> <style scoped> .com { overflow-y: auto; min-height: 300px } .comApp>ul, .comApp>div { margin: 10px; display: inline-block; vertical-align: top; } </style>
接收参数:
vue<!-- 1 定义组件模版 --> <template> <div> css 详情 <div>id:{{ query.id }}</div> <div>title:{{ query.title }}</div> <div>content:{{ query.content}}</div> </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="detail"> import { ref ,toRef,toRefs,onMounted,onUnmounted} from 'vue' import {useRoute} from 'vue-router' let route = useRoute(); let query = toRef(route,'query') console.log("query参数") onMounted(()=>{ console.log("CSS Detail 组件 挂载"); }) onUnmounted(()=>{ console.log("CSS Detail 组件卸载"); }) </script> <!-- 3 定义样式 --> <style scoped> div{ margin: 5px; } </style>
params参数
传递参数
vue<!-- 跳转并携带params参数(to的字符串写法) --> <!-- <router-link :to="`/css/detail/${chapter.id}/${chapter.title}/${chapter.content}`"></router-link> --> <!-- 跳转并携带params参数(to的对象写法) --> <router-link :to="{ name:'CssDeatail', //用name跳转 params:{ id:chapter.id, title:chapter.title, content:chapter.content } }" > {{ chapter.title }} </router-link>
在路由中进行占位定义
typescriptimport {createRouter,createWebHistory,createWebHashHistory} from 'vue-router' import CSS from '@/views/CSS.vue' import HTML from '@/views/HTML.vue' import JavaScript from '@/views/JavaScript.vue' import JavaScriptChapter1 from '@/views/js/chapter1.vue' import JavaScriptChapter2 from '@/views/js/chapter2.vue' import CSSDetail from '@/views/css/detail.vue' const router = createRouter({ history:createWebHistory(), // history:createWebHashHistory(), routes:[ { path:'/', redirect:'/html' }, { path:'/html', component:HTML }, { name:"ToCSS", path:'/css', component:CSS, children:[ { name:'CssDeatail', path:'detail/:id/:title/:content', component:CSSDetail, } ] }, { path:'/js', component:JavaScript, children:[ { path:'/js/chapter1', component:JavaScriptChapter1 }, { path:'/js/chapter2', component:JavaScriptChapter2 }, ] } ] }) export default router
接收参数:
vue<!-- 1 定义组件模版 --> <template> <div> css 详情 <div>id:{{ params.id }}</div> <div>title:{{ params.title }}</div> <div>content:{{ params.content }}</div> </div> </template> <!-- 2 定义组件逻辑 --> <script setup lang="ts" name="detail"> import { ref, toRef, toRefs, onMounted, onUnmounted } from 'vue' import { useRoute } from 'vue-router'
let route = useRoute(); let params = toRef(route, 'params') console.log("params参数") onMounted(() => { console.log("CSS Detail 组件 挂载"); }) onUnmounted(() => { console.log("CSS Detail 组件卸载"); }) </script> <!-- 3 定义样式 --> <style scoped> div { margin: 5px; } </style>
备注1:传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。备注2:传递
params
参数时,需要提前在规则中占位。
4.9. 【路由的props配置】传送门
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件)
在路由组件中使用props接收数据
vue
<!-- 1 定义组件模版 -->
<template>
<div>
css 详情
<div>id:{{ id }}</div>
<div>title:{{ title }}</div>
<div>content:{{ content }}</div>
</div>
</template>
<!-- 2 定义组件逻辑 -->
<script setup lang="ts" name="detail">
defineProps(['id','title','content'])
</script>
<!-- 3 定义样式 -->
<style scoped> div {
margin: 5px;
}
</style>
传参的使用
html
<router-link
:to="{
name:'CssDeatail',
name:{
id:chapter.id,
title:chapter.title,
content:chapter.content
}
}"
>
修改路由表中传参方式
json
{
name:'CssDeatail',
path:'detail/:id/:title/:content',
component:CSSDetail,
//1 props的对象写法,作用:把对象中的每一组key-value作为props传给CssDeatail组件 ,对path没有具体要求,可以不写,写上也不算错
//props:{id:'test00001',title:'固定的title',content:'详情内容 content....'}
//2 props的布尔值写法,作用:把收到了每一组params参数,作为props传给CssDeatail组件
// path:'detail/:id/:title/:content',
// props:true
//3 props的函数写法,作用:把返回的对象中每一组key-value作为props传给CssDeatail组件
// path:'detail', 不能出现 冒号“:”
// props:(route)=>{
// //此处应该 :to中传递的是 query参数才有意义,否则取不到query参数的值,params参数不需要使用函数也可以获取到,`即props:true`
// return {
// id:route.query.id,
// title:route.query.title,
// content:route.query.content
// }
// }
//函数的其他写法
props(route){
return route.query
}
}
4.10. 【 replace属性】
作用:控制路由跳转时操作浏览器历史记录的模式。
浏览器的历史记录有两种写入方式:分别为
push
和replace
:push
是追加历史记录(默认值)。replace
是替换当前记录。
开启
replace
模式:vue<RouterLink replace .......>News</RouterLink>
4.11. 【编程式导航】
路由组件的两个重要的属性:$route
和$router
变成了两个hooks
js
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)
4.12. 【重定向】
作用:将特定的路径,重新定向到已有路由。
具体编码:
js{ path:'/', redirect:'/about' }
