Javaweb - 14.5 Vue3 路由机制
目录
路由简介
什么是路由:
定义:路由就是根据不同的 URL 地址展示不同的内容或页面
作用:
SPA 中,可以实现不同视图之间的无刷新切换
实现页面认证和权限控制
路由入门案例
案例需求:

创建项目和导入路由依赖:
npm create vite@4
npm install
npm install vue-router@4 --save
准备页面组件

单独在 src 文件夹下面创建一个 routers 文件夹,里面存放 router.js

// 导入创建路由对象需要的函数
import {createRouter,createWebHashHistory} from 'vue-router'
// 导入 .vue 组件
import Home from '../comments/Home.vue'
import List from '../comments/List.vue'
import Add from '../comments/Add.vue'
import Update from '../comments/Update.vue'
// 创建一个路由对象
const router = createRouter({
// history 属性用于记录路由的历史
history:createWebHashHistory(),
// routes 用于定义多个不同的路径和组件之间的对应关系
routes:[
{
path:'/home',
component:Home
},
{
path:'/list',
component:List
},
{
path:'/add',
component:Add
},
{
path:'/update',
component:Update
},
{
path:'/',
component:Home
}
]
})
// 向外暴露
export default rouer
配置 main.js 文件:
import { createApp } from 'vue'
import App from './App.vue'
// 在整个 App.vue 中可以使用路由
import router from './routers/router.js'
const app = createApp(App)
// 绑定路由对象
app.use(router)
// 挂载视图
app.mount('#app')
App.vue 的页面
<script setup>
</script>
<template>
<div>
App 开头的内容 <br>
<router-link to = "/Home">Home页</router-link><br>
<router-link to = "/List">List页</router-link><br>
<router-link to = "/Add">Add页</router-link><br>
<router-link to = "/Update">Update页</router-link><br>
<hr>
<!-- router-view 标签会背替换成具体的 .vue -->
<router-view></router-view>
<hr>
App 结束的内容
</div>
</template>
<style scoped>
</style>
这样,就基础的实现了我们的需求:

我们还可以在不同的页面中进行相互跳转:
例如,在 Home 页中同样加一个 router-link 标签,实现从 Home 页向 Add 页的跳转:
<script setup>
</script>
<template>
<div>
<router-link to="/add">Add页</router-link>
<h1> Home 页面</h1>
</div>
</template>
<style scoped>
</style>
也可以实现重定向,比如当我们的路径为 /showAll 的时候,重定向到 /list:
先在 router.js 中的 router 对象中,配置 path 和对应的 redirect

然后在 App.vue 中添加 router-link 的标签即可

编程式路由(useRouter)
声明式路由:
<router-link to = "/list">list页</router-link> 这种路由,点击后只能切换 /list 对应的组件,是固定的
编程式路由:
通过 useRouter,动态决定向那个组件切换的路由
这里的 useRouter 方法返回的是一个 router 对象,可以用它来做,如导航到新页面,返回上一面等操作
<script setup>
import {useRouter} from 'vue-router'
import {ref} from 'vue'
let myPath = ref('')
const router = useRouter()
function showList() {
// 编程式路由实现页面跳转
// 方式一:router.push("/list")
router.push({path:"/list"})
}
function goMyPage() {
router.push(myPath.value)
}
</script>
<template>
<div>
<!-- 声明式路由 -->
<router-link to="/home">home</router-link><br>
<router-link to="/list">list</router-link><br>
<router-link to="/add">add</router-link><br>
<router-link to="/update">update</router-link><br>
<!-- 编程式路由 -->
<button @click="showList()">list</button><br>
<button @click="goMyPage()">Go</button><input type = "text" v-model="myPath">
<router-view></router-view>
</div>
</template>
<style scoped>
</style>
路由传参(useRoute)
路径参数:
在路径中使用一个动态字段来实现,我们称之为路径参数。
例如:查看数据详情 /showDetail/1, 1 就是要查看详情的 id,可以动态填值。
键值对参数:
类似与 get 请求通过 URL 传参,数据是键值对形式的。
例如:查看数据详情 /showDetail?hid=1,hid 就是要传递的键值对参数。
读取参数:
在 Vue3 和 Vue Router4 中,我们可以使用 useRoute 这个函数,从 Vue 的组合式 API 中获取路由对象。
useRoute 方法返回的是当前的 route 对象,我们可以用它来获取关于当前路由的信息,如当前的路径,键值对参数等。
案例需求:切换到 ShowDetail.vue 组件时,向该组件通过路由传递参数
1.路径参数:{声明式路由和编程式路由}
准备一个 ShowDetail.vue 页面:
<script setup>
</script>
<template>
<div>
<h1>ShowDetail接收路径参数</h1>
</div>
</template>
<style scoped>
</style>
在 router.js 中进行配置:
// 导入创建路由的相关方法
import { createRouter, createWebHashHistory } from "vue-router";
// 导入 .vue 组件
import Home from '../components/Home.vue'
import Add from '../components/Add.vue'
import List from '../components/List.vue'
import Update from '../components/Update.vue'
import ShowDetail from '../components/ShowDetail.vue'
const router = createRouter({
history:createWebHashHistory(),
routes:[
{
path:"/showDetail/:id/:language",
component:ShowDetail
},
{
path:"/",
component:Home,
},
{
path:"/home",
component:Home,
},
{
path:"/list",
component:List,
},
{
path:"/add",
component:Add,
},
{
path:"/update",
component:Update
}
]
})
export default router
ShowDetail.vue:
<script setup>
/**
* 接收传递过来的路径参数
* useRoute 函数是用来接收参数的
*/
import {useRoute} from 'vue-router'
import {ref,onUpdated} from 'vue'
let languageId = ref(0)
let languageName = ref("")
let route = useRoute()
languageId.value=route.params.id
languageName.value=route.params.language
// 让页面可以实时更新~
onUpdated(()=>{
languageId.value=route.params.id
languageName.value=route.params.language
})
</script>
<template>
<div>
<h1>ShowDetail接收路径参数</h1>
<h3>{{languageId}}{{languageName}}是世界上最好的语言</h3>
</div>
</template>
<style scoped>
</style>
App.vue:
<script setup>
import {useRouter} from 'vue-router'
import {ref} from 'vue'
const router = useRouter()
function showDetail(id,language){
router.push(`/showDetail/${id}/${language}`)
}
</script>
<template>
<div>
<router-link to="/showDetail/1/java">声明式路由路径传参</router-link>
<button @click="showDetail(2,'PHP')">编程式路由路径传参</button>
<hr>
<router-view></router-view>
</div>
</template>
<style scoped>
</style>
2. 键值对参数{声明式路由和编程式路由}
router.js:
// 导入创建路由的相关方法
import { createRouter, createWebHashHistory } from "vue-router";
// 导入 .vue 组件
import Home from '../components/Home.vue'
import Add from '../components/Add.vue'
import List from '../components/List.vue'
import Update from '../components/Update.vue'
import ShowDetail from '../components/ShowDetail.vue'
import ShowDetail2 from '../components/showDetail2.vue'
const router = createRouter({
history:createWebHashHistory(),
routes:[
{
path:"/showDetail2",
component:ShowDetail2
},
{
path:"/showDetail/:id/:language",
component:ShowDetail
},
{
path:"/",
component:Home,
},
{
path:"/home",
component:Home,
},
{
path:"/list",
component:List,
},
{
path:"/add",
component:Add,
},
{
path:"/update",
component:Update
}
]
})
export default router
ShowDetail2:
<script setup>
/**
* 接收传递过来的路径参数
* useRoute 函数是用来接收参数的
*/
import {useRoute} from 'vue-router'
import {ref,onUpdated} from 'vue'
let languageId = ref(0)
let languageName = ref("")
let route = useRoute()
languageId.value=route.query.id
languageName.value=route.query.language
onUpdated(()=>{
languageId.value=route.query.id
languageName.value=route.query.language
})
</script>
<template>
<div>
<h1>ShowDetail2接收键值对参数</h1>
<h3>{{languageId}}{{languageName}}是世界上最好的语言</h3>
</div>
</template>
<style scoped>
</style>
App.vue:
<script setup>
import {useRouter} from 'vue-router'
import {ref} from 'vue'
const router = useRouter()
function showDetail(id,language){
router.push(`/showDetail/${id}/${language}`)
}
function showDetail2(id,language){
router.push(`/showDetail2?id=${id}&language=${language}`)
}
</script>
<template>
<div>
<router-link to ="/showDetail2?id=1&language=java">声明式路由键值对传参</router-link>
<button @click="showDetail2(2,'PHP')">编程式路由键值对传参</button>
<hr>
<router-view></router-view>
</div>
</template>
<style scoped>
</style>
路由守卫
在 Vue3 中,路由首位是用于在路由切换期间,进行一些特定任务的回调函数。路由守卫可以用于许多任务:例如验证用户是否已经登录,在路由切换前提供确认提示,请求数据等。
全局前置守卫:在路由切换前被调用,可以用于验证用户是否已登录,中断导航,请求数据等。
全局后置首位:在路由切换之后被调用,可以用于处理数据,操作 DOM,记录日志等
守卫代码的位置:在 router.js 文件中
// 设置全局前置首位
// 每次路由切换页面前,都会执行 beforeEach 中的回调函数
router.beforeEach(
(to,from,next)=>{
/**
* from 上一个页面 表示从哪里来
* to 下一个页面 表示到哪里去
* next 放行的方法,只有执行了该方法,才会放行路由 类似与过滤器中的 filterChain.doFilter
* next() 放行
* next("/路径") 路由的重定向,可以转发到其他地址
* 但是到达目标组件前会在此经过前置路由守卫,需要注意判断,避免无限重定向
*
*
*/
console.log("beforeEach")
console.log(from.path)
console.log(to.path)
next()
}
)
// 设置全局后置路由
// 每次路由切换页面后,都会执行 afterEach 中的回调函数
router.afterEach(
()=>{
console.log("afterEach")
}
)
案例测试
要求:登录案例,登录以后才可以进入 home 页面,否则必须进入 login 页面
Login.vue:
<script setup>
import {ref} from 'vue'
import {useRouter} from 'vue-router'
let username = ref('')
let password = ref('')
let router = useRouter()
let login = () => {
console.log(username.value, password.value)
if (username.value == 'root' && password.value == '123456') {
router.push({path:'/home',query:{'username':username.value}})
// 登录成功利用前端存储机制,存储账号
localStorage.setItem('username', username.value)
} else {
alert("登陆失败,账号或密码错误")
}
}
</script>
<template>
<div>
账号:<input type = "text" v-model="username" placeholder="请输入账号"><br>
密码:<input type = "password" v-model="password" placeholder="请输入密码"><br>
<button @click="login()">登录</button>
</div>
</template>
<style scoped>
</style>
Home.vue:
<script setup>
import {ref} from 'vue'
import {useRouter, useRoute} from 'vue-router'
let route = useRoute()
let router = useRouter()
let username = window.localStorage.getItem('username')
let logout = () => {
//清楚 localStorge 中的 username
window.localStorage.removeItem('username')
// 动态路由到登录页
router.push('/login')
}
</script>
<template>
<div>
<h1> Home 页面</h1>
<h3>欢迎{{username}}登录</h3>
<button @click="logout()">退出登录</button>
</div>
</template>
<style scoped>
</style>
App.vue:
<script setup>
</script>
<template>
<div>
<router-view></router-view>
</div>
</template>
<style scoped>
</style>
定义 routers.js:
import { createRouter, createWebHashHistory } from "vue-router";
import Home from "../components/Home.vue";
import Login from "../components/Login.vue";
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: "/home",
component: Home,
},
{
path:"/",
component:Home
},
{
path:"/login",
component:Login
}
],
});
// 设置路由的全局前置首位
router.beforeEach(
(to,from,next) => {
console.log(`从哪里来:${from.path},到哪里去${to.path}`)
if (to.path == '/login') {
next()
} else {
let username = window.localStorage.getItem("username")
if (null != username) {
next()
} else {
next("/login")
}
}
}
)
// 设置路由的全局后置首位
router.afterEach(
(to, from) => {
console.log(`从哪里来:${from.path},到哪里去${to.path}`)
}
)
// 对外暴露路由对象
export default router
修改 main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './routers/router'
let app = createApp(App)
app.use(router)
app.mount('#app')
测试无误~
补充:
路由传参:useRoute,编程式路由:useRouter:


完!
更多推荐
所有评论(0)