一、Vue Router的安装
1.创建项目

注:Vue3对应的是Router4版本,Vue2对应的是Router3版本
2.下载router
下载前

下载后
@4是版本,也可以写@4.2.5
--save是使用路由
yarn add vue-router@4 --save

二、Vue Router的基本使用
1.目录结构

2.案例代码
About
<template>
<div class="about-container">
<h3>About组件</h3>
</div>
</template>
<style scoped>
.about-container {
min-height: 150px;
background-color: #f2f2f2;
padding: 15px;
}
</style>
Home
<template>
<div class="home-container">
<h3>Home组件</h3>
</div>
</template>
<style scoped>
.home-container {
min-height: 150px;
background-color: #f2f2f2;
padding: 15px;
}
</style>
App根组件
<template>
<div class="app-container">
<h1>App根组件</h1>
<!-- router-link:定义导航链接 -->
<!-- to:指定链接的地址,与路由中的path对应 -->
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<hr />
<!-- 路由对应组件显示的位置 -->
<router-view></router-view>
</div>
</template>
<style scoped>
.app-container {
text-align: center;
font-size: 16px;
}
.app-container a {
padding: 10px;
color: #000;
}
.app-container a.router-link-active {
color: #fff;
background-color: #000;
}
</style>
router.js
版本一:一次直接加载所有组件
import {createRouter, createWebHistory} from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'
const routes = createRouter({
history: createWebHistory(),//history:指定路由模式,createWebHistory()是HTML5的history模式
routes:[
{path:'/home',component:Home},
{path:'/about',component:About},
]
})
export default routes
版本二:懒加载动态加载
import {createRouter, createWebHistory} from 'vue-router'
// import Home from './components/Home.vue'
// import About from './components/About.vue'
const routes = createRouter({
history: createWebHistory(),//history:指定路由模式,createWebHistory()是HTML5的history模式
routes:[
{path:'/home',component:()=>import('./components/Home.vue')},
{path:'/about',component:()=>import('./components/About.vue')},
]
})
export default routes
main.js
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// 1.引入路由模块
import router from './router.js'
const app = createApp(App)
// 2.注册路由模块
app.use(router)
app.mount('#app')
3.效果



三、路由重定向
在第二点案例的基础上,添加重定向代码
router.js

效果
输入http://localhost:5173/会跳转到http://localhost:5173/home
四、嵌套路由
1.目录结构
1.在conponents下新建pages文件夹
2.在pages下新建文件

2.案例代码编写
Tab1
<template>
<div>Tab1组件</div>
</template>
<style scoped>
div{
text-align: left;
background-color: #9dc4e5;
}
</style>
Tab2
<template>
<div>Tab2组件</div>
</template>
<style scoped>
div{
text-align: left;
background-color: #ffba00;
}
</style>
About
在第三点的案例基础上


router.js
注:嵌套组件的路径不加''/''

效果



五、动态路由
1.监听路由
添加到About

效果

2.获取动态路径参数值
法1:$route.params
在components下创建Movie

在根组件App下添加目标地址

在pages下,添加MovieDetails

将Movie和MovieDetails添加到router.js中

效果

法2:props
修改MovieDetails

修改router.js

六、命名路由
模板:
注:name属性是唯一的


修改Home

修改router.js
注:大小写要一致

效果

七、编程式导航
1.两种导航方式
- 声明式导航:<router-link>标签
- 编程式导航:useRouter()函数
2.编程式导航方法
1.push()
push()方法会向历史记录中添加一个新的记录,以编程方式导航到一个新的URL。当用户单击浏览器后退按钮时,会回到之前的URL。push()方法的参数可以是一个字符串路径,或者一个描述地址的对象
router.push('/about/tab1') // 字符串路径
router.push({ path: '/about/tab1' }) // 带有路径的对象
router.push({ name: 'user', params: { userId: '123'} }) // 命名路由
router.push({ path: '/user', query: { id: '1' } }) // 带查询参数,如:/user?id=1
router.push({ path: '/user', hash: '#admin' }) // 带有Hash值,如:/user#admin
如果在参数的对象中提供了path,则params会被忽略。为了传递参数,需要提供路由的name或者手动拼接带有参数的path
const id = '123'
router.push({ name: '/user', params: { userId } }) // 跳转到/user/123
router.push({ path: `/user/${userId}` }) // 跳转到/user/123
// 以下是params不生效的情况
router.push({ path: '/user', params: { userId } }) // 跳转到/user
案例
修改Home:用编程式导航代替声明式导航

2.replace()
replace()方法在导航后不会向历史记录中添加新的记录,而是会替换历史记录中的当前记录。
在声明式导航中,为<router-link>标签添加replace属性也能实现与replace()方法类似的效果。
// 编程式导航
router.replace({ path: '/user' })
<!-- 声明式导航 -->
<router-link :to="{ path: '/user' }" replace></router-link>
3.go()
go()方法用于实现前进或后退的效果,其参数表示历史记录中前进或后退的步数,类似于window.history.go(),相应的地址栏也会发生改变。
- go(1)表示前进一条记录。
- go(-1)表示后退一条记录。
案例

效果


八、导航守卫
导航守卫用于控制路由的访问权限。
1.规则
const router = createRouter()
router.beforeEach((to, from, next) => {})//定义全局前置守卫
router.afterEach((to, from, next) => {})//定义全局后置守卫
每个全局导航守卫方法中接收3个形参:to、from和next。
to:表示目标路由对象;
from:表示当前导航正要离开的路由对象;
next:next为函数,如果不接收next()函数,则默认允许用户访问每一个路由;
如果接收了next()函数,则必须调用next()函数,否则不允许用户访问任何一个路由。
2.案例
在conponents下创建Login

在router.js下添加

效果


九、后台管理系统
1.准备工作
1.1创建项目
创建命令:
npm create vite@4.1.0 manage-system
选择:

打开vscode,运行项目
// 运行命令
npm run dev
// 下载依赖
npm install

1.2下载router
下载命令:
yarn add vue-router@4 --save

在src文件夹下创建router.js,编写router.js的基本代码

修改mian.js

2.渲染登录组件
2.1把Login写入router

2.2清空App,导入router视图

3.实现登录功能
在components文件夹下创建Login,编写Login代码
<template>
<div class="login-container">
<div class="login-box">
<!-- 头像区域 -->
<div class="avatar-box">
<img src="../assets/logo.png" class="avatar" />
</div>
<!-- 表单区域 -->
<div class="form-login">
<!-- 登录名称 -->
<div class="form-group">
<label for="username">登录名称:</label>
<input type="text" class="form-control" id="username" placeholder="请输入登录名称" autocomplete="off" v-model.trim="username"/>
</div>
<!-- 登录密码 -->
<div class="form-group">
<label for="password">登录密码:</label>
<input type="password" class="form-control" id="password" placeholder="请输入登录密码" v-model.trim="password"/>
</div>
<!-- 登录按钮 -->
<div class="form-group">
<button type="button" class="btn" @click="onLogin">登录</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const username = ref('')
const password = ref('')
const router = useRouter()
const onLogin = () => {
if (username.value === 'admin' && password.value === '123456') {
router.push('/home')
return localStorage.setItem('token', 'Bearer xxx')//保存token
} else {
alert('用户名或密码错误')
localStorage.removeItem('token')//清除token
}
}
</script>
4.渲染后台主页组件
4.1编写首页相关代码
在components下创建Home,编写Home

在components下创建subcomponents文件夹,
在subcomponents下创建MyHeader和MyAside
MyHeader

MyAside

router
将子组件添加到router下

4.2创建各侧边栏子组件
目录

内容

5.实现退出功能
MyHeader

6.全局控制路由访问权限
router

7.渲染用户管理页面的数据

8.跳转到用户详情页
在components下创建文件夹users
在users文件夹下创建vue文件MyUserDetail
在router中填写MyUserDetail路径

9.使用props获取用户编号
router添加props

MyUserDetail编写代码

10.解决详情页左侧菜单激活问题

11.解决样式问题
11.1未添加样式


11.2添加样式


11.3样式代码
MyHeader
<style scoped>
.layout-header-container {
height: 60px;
border-bottom: 1px solid #eaeaea;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.5rem;
background-color: #5f9ea0;
.layout-header-left{
display: flex;
align-items: center;
color: #fff;
}
}
.layout-header-left-img {
height: 50px;
}
.layout-header-right{
.btn{
background-color: #5f9ea0;
color: #fff;
}
.btn:hover{
color: #999;
opacity: 0.5;
background-color: #fff;
}
}
</style>
MyAside
<style scoped>
.layout-aside-container {
width: 250px;
height: 100%;
border-right: 1px solid #eaeaea;
}
.menu {
list-style-type: none;
padding: 0;
.menu-item {
line-height: 50px;
font-weight: bold;
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
&:hover {
background-color: #efefef;
cursor: pointer;
}
a {
display: block;
color: black;
padding-left: 30px;
&:hover {
text-decoration: none;
}
}
}
}
/* 设置路由高亮效果 */
.router-link-active {
background-color: #efefef;
box-sizing: border-box;
position: relative;
/* 伪元素实现路由高亮效果 */
&::before {
content: ' ';
display: block;
width: 4px;
height: 100%;
position: absolute;
left: 0;
top: 0;
background-color: #42b983;
}
}
</style>
MyUserDetail
<style scoped>
button{
background-color: #409eff;
color: #fff;
}
</style>
Home
<style>
.home-container {
height: 100%;
display: flex;
flex-direction: column;
.home-main-box {
height: 100%;
display: flex;
.home-main-body {
padding: 15px;
flex: 1;
}
}
}
</style>
Login
<style scoped>
.login-container {
background-color: #35495e;
height: 100%;
.login-box {
width: 400px;
height: 250px;
background-color: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 6px rgba(255, 255, 255, 0.5);
.form-login {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
box-sizing: border-box;
padding: 1.5rem!important;
.form-group{
padding-top: 20px;
.btn{
background-color:deepskyblue;
color: #fff;
}
}
}
}
}
.form-control{
flex: 1;
padding: 0.5rem;
}
.avatar-box {
position: absolute;
width: 100%;
top: -65px;
left: 0;
.avatar {
width: 120px;
height: 120px;
border-radius: 50% !important;
box-shadow: 0 0 6px #efefef;
background-color: #fff;
}
}
</style>
style.css
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
/* body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
} */
body {
margin: 0;
display: flex;
place-items: center;
height: 100%;
}
html{
height: 100%;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
/* #app {
width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
} */
#app {
width: 100%;
margin: 0 auto;
text-align: center;
height: 100%;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
12.完整代码
目录

代码
省略。。。