后端路由
- 客户端请求不同的URL
- 服务器匹配URL并给一个Controller处理
- Controller处理完返回渲染好的HTML页面或数据给前端
优点:
不需要单独加载js和css,直角交给浏览器展示,有利于SEO优化
缺点:
页面有后端人员编写或由前端人员使用PHP/Java编写
前端路由
- 前后端分离:后端提供API,前端渲染数据到页面上
- SPA(单页面富应用):前后端分离+前端路由
- 前端路由核心:URL和组件相互映射。改变URL,页面不整体刷新
改变URL 页面不刷新的两种模式
- URL的hash(锚点#),H5的API location
<template>
<div>
<a href="#/home">首页/</a>
<a href="#/about">关于/</a>
<div class="router-view" ref="divRef"></div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
// 获取DOM
let divRef = ref()
// DOM挂载完成
onMounted(() => {
// 监听hash值的改变(相当与监听URL的改变)
window.addEventListener('hashchange', () => {
switch (location.hash) {
case "#/home":
divRef.value.innerHTML = "home"
break;
case "#/about":
divRef.value.innerHTML = "about"
break;
default:
divRef.value.innerHTML = "default"
break;
}
})
})
</script>
- H5新增API的history
history实例方法,改变URL而不刷新页面:
back()
forward()
go()
pushState()
replaceState()
基本使用
路由映射文件
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('@/views/AboutView.vue')
}
]
})
export default router
App.vue
<template>
<div>
<!-- 字符串形式 -->
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<!-- 对象形式 -->
<router-link :to="{ path: '/about' }">关于</router-link>
<!-- 路由出口 -->
<router-view></router-view>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
</script>
<style scoped>
/* 高亮 */
.router-link-active {
color: red;
font-size: 20px;
}
</style>
动态路由(路径参数)
params参数
动态路由:根据匹配模式,不同路径的路由映射到同一个组件
匹配模式 | 匹配路径 | $route.params |
---|---|---|
/users/:username | /users/eduardo | { username: 'eduardo' } |
/users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
匹配模式
{
path: '/user/:id',
name: 'user',
component: () => import('@/views/UserView.vue')
}
App.vue传递参数
<template>
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<!-- 给路由传参 -->
<router-link :to="{ path: `/user/${id}` }">用户{{ id }}</router-link>
<router-link to="/user/2">用户2</router-link>
<!-- 路由出口 -->
<router-view></router-view>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
let id = ref(100)
</script>
<style scoped>
/* 高亮 */
.router-link-active {
color: red;
font-size: 20px;
}
</style>
UserView.vue接收参数
<template>
<div>
<!--
UserView接收到params参数,根据不同id进行不同操作
-->
<h1>user-{{ $route.params.id }}</h1>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useRoute } from 'vue-router';
const route = useRoute()
console.log(route.params);
</script>
query参数
App.vue传递query参数
const router = useRouter()
function handleClick() {
router.push({
path: '/user/2',
query: {
name: 'cjc',
age: 999
}
})
}
// http://127.0.0.1:5173/user/2?name=cjc&age=999
UserView.vue接收参数
<!-- query参数 -->
<h1>query-{{ $route.query }}</h1>
const route = useRoute()
console.log(route.query);
路由改变 组件复用
用户从 /user/1 导航到 /user/2 时,相同的组件实例UserView被重复使用。
因为组件没有销毁创建,故组件的生命周期钩子不会被调用
监听同一路由组件的路径参数的变化:
方式1 在UserView中使用watch
// 监听参数变化
watch(() => route.params, (toParams, previousParams) => {
// 对路由变化做出响应
console.log('toParams:', toParams);
console.log('previousParams:', previousParams);
})
方式2 在UserView中使用onBeforeRouteUpdate
onBeforeRouteUpdate((to, from) => {
console.log('to:', to.params);
console.log('from:', from.params);
})
404
{
//path: '/:pathMatch(.*)' 匹配内容以/形式
//path: '/:pathMatch(.*)*' 匹配内容以数组形式
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/NotFound.vue')
}
将匹配所有内容并将其放在 $route.params.pathMatch
中
编程式路由导航
$router相关API
- go
- forward
- back
- push
- replace
动态添加路由
router/index.js
...
// 动态添加路由
// 添加一级路由
router.addRoute({
path: '/test',
name: 'test',
component: () => import("@/views/TestView.vue")
})
// 添加二级路由
router.addRoute("test", {
path: '/testChild',
name: 'testChild',
component: () => import("@/views/TestChildView.vue")
})
// 检查路由是否存在
console.log(router.hasRoute('test'));
// 路由器router中所有路由
console.log(router.getRoutes());
// 删除路由
router.removeRoute('test')
console.log(router.getRoutes());
路由导航守卫
全局前置守卫beforeEach
参数
- to “到哪去”的路由对象
- from “从哪来”的路由对象
返回值
- return false 取消当前导航
- return;或return undefined;都是默认导航。等同于return to.path;
- return 路由地址(string|对象(包含path,query,params))