
目录
路由的概念在软件工程中出现,最早是在后端路由中实现的 :
早期的网站开发整个HTML页面是由服务器来渲染的,服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示
多页面服务器如何处理 :
上面的这种操作, 就是后端路由 :
后端路由的缺点 :
前端渲染的理解 :
前后端分离阶段 :
单页面富应用阶段 :

history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面

目前前端流行的三大框架, 都有自己的路由实现 :
Vue Router :
npm install vue-router

在根目录下创建router文件夹,并在其中创建index.js
- // 1. 导入创建路由对象 和 创建hash对象
- import { createRouter, createWebHashHistory } from 'vue-router';
-
- // 2. 导入组件
- import Home from '../views/Home.vue';
- import About from '../views/About.vue';
-
- // 3. 配置路由映射关系表
- const routes = [
- // 路径和组件映射起来
- { path: '/home', component: Home },
- { path: '/about', component: About }
- ];
-
- // 4. 创建路由对象
- const router = new createRouter({
- // 5. 配置路由跳转模式,这里使用 hash 模式
- history: createWebHashHistory(),
- // 把映射表放入
- routes
- });
-
- // 5. 导出
- export default router;
- import { createApp } from 'vue';
- import App from './App.vue';
-
- // 1. 导入路由对象
- import router from './router';
-
- // 2. 使用use调用一下
- createApp(App).use(router).mount('#app');
router-link => 跳转链接
router-view => 组件显示的位置
- <template>
- <div class="app">
- App 页面
- <br />
- <br />
-
-
- <router-link to="/home">Homerouter-link>
-
- <br />
- <router-link to="/about">Aboutrouter-link>
- <br />
- <br />
-
-
- <router-view>router-view>
- div>
- template>

以让路径默认跳到到首页
path配置的是根路径: / => redirect是重定向
- const routes = [
- // 默认显示的页面 => home
- { path: '/', redirect: '/home' },
- { path: '/home', component: Home },
- { path: '/about', component: About }
- ];
- // 1. 导入创建路由对象
- /**
- * createWebHashHistory : hash模式
- * createWebHistory : history模式
- */
- import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
-
- import Home from '../views/Home.vue';
- import About from '../views/About.vue';
-
- const routes = [
- { path: '/', redirect: '/home' },
- { path: '/home', component: Home },
- { path: '/about', component: About }
- ];
-
- const router = new createRouter({
- // 使用history模式
- history: createWebHistory(),
- routes
- });
-
- // 5. 导出
- export default router;
- const routes = [
- {
- path: '/',
- redirect: '/home'
- },
- {
- name: 'home',
- path: '/home',
- component: Home,
- meth: {
- name: 'coderstar',
- age: 28
- }
- },
- {
- name: 'about',
- path: '/about',
- component: About
- }
- ];
对于哪些没有匹配到的路由,通常会匹配到固定的某个页面
- // 如果匹配到任何一个不存在的路径,就显示这个组件
- {
- name: 'notFound',
- path: '/:pathMatch(.*)', // => 地址一样的显示出来 => abc/erfsdf/gsa/e
- path: '/:pathMatch(.*)*', // => 如果遇到分级,会解析 / ,变成一个数组 => ['abc','erfsdf','gsa','e']
- component: () => import('../views/NotFound.vue')
- }
- <template>
- <div>NotFound : 抱歉,出错了,未找到该页面div>
- <h2 class="not-found">出错路径为 : {{ $route.params.pathMatch }}h2>
- template>
-
- <script setup>
- import { useRoute } from 'vue-router';
-
- const route = useRoute();
- console.log(route.params.pathMatch);
- script>
-
- <style lang="less" scoped>
- .not-found {
- color: red;
- }
- style>

router-link => 有很多属性可以配置
to : 是一个字符串,或者是一个对象
指定跳转到哪个组件
- <router-link to="/home">Homerouter-link>
-
- <router-link :to="{ path: '/home' }">Homerouter-link>
不设置的时候
使用的是 router.push() ,可以点击浏览器的返回,回到上一次记录页面
设置的时候
使用的是router.replace(),无法返回到上一次记录页面
- <router-link to="/home" replace>Homerouter-link>
-
- <router-link to="/about">Aboutrouter-link>
设置激活a元素后应用的class,默认是router-link-active

- <router-link to="/home" active-class="acttttive">Homerouter-link>
-
- <router-link to="/about">Aboutrouter-link>
链接精准激活时,应用于渲染的 的 class,默认是router-link-exact-active
ps : 精准定位路由,用于嵌套路由中
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载
- const routes = [
- {
- path: '/',
- redirect: '/home'
- },
- {
- name: 'home',
- path: '/home',
- // 路由懒加载
- component: () => import('../views/Home.vue'),
- meth: {
- name: 'coderstar',
- age: 28
- }
- },
- {
- name: 'about',
- path: '/about',
- // 路由懒加载
- component: () => import('../views/About.vue')
- }
- ];
webpack从3.x开始支持对分包进行命名(chunk name)
- const routes = [
- {
- path: '/',
- redirect: '/home'
- },
- {
- name: 'home',
- path: '/home',
- // 路由懒加载
- component: () => import('../views/Home.vue'),
- meth: {
- name: 'coderstar',
- age: 28
- }
- },
- {
- name: 'about',
- path: '/about',
- // 路由懒加载,可以顺便设置分包后的名称
- component: () => import(/* webpackChunkName: 'about' */ '../views/About.vue')
- }
- ];

很多时候需要将给定匹配模式的路由映射到同一个组件
- {
- name: 'user',
- // 动态设定 id 和 name
- path: '/user/:id/:name',
- component: () => import('../views/User.vue')
- }
- <router-link to="/user/111111/coder">User => 1router-link>
- <br />
- <router-link to="/user/222222/star">User => 2router-link>
- <template>
-
- <div>我是用户user => {{ $route.params.id }} - {{ $route.params.name }}div>
- template>
-
- <script setup>
- import { useRoute, onBeforeRouteUpdate } from 'vue-router';
- // 2. 在js中获取
-
- // 第一次获取
- const route = useRoute();
- console.log(route.params.id, route.params.name);
-
- // 切换的时候获取
- onBeforeRouteUpdate((to, from) => {
- // 当前
- console.log('to:', to.params.id, to.params.name);
- // 从哪里来
- // console.log('from:', from.params.id, from.params.name);
- });
- script>

路由嵌套 : 组件的内部可能有多个组件来回切换

- const routes = [
- {
- path: '/',
- redirect: '/home'
- },
- {
- name: 'home',
- path: '/home',
- component: () => import('../views/Home.vue'),
- meth: {
- name: 'coderstar',
- age: 28
- },
- // 配置子路由
- children: [
- {
- // 配置重定向,默认进去 home组件 中的 A组件
- path: '/home',
- redirect: '/home/A'
- },
- {
- // 注 : 这里不需要写全称 => /home/a
- path: 'a',
- component: () => import('../views/HomeA.vue')
- },
- {
- // 注 : 这里不需要写全称 => /home/b
- path: 'b',
- component: () => import('../views/HomeB.vue')
- }
- ]
- },
- {
- name: 'about',
- path: '/about',
- component: () => import('../views/About.vue')
- },
- {
- name: 'user',
- path: '/user/:id/:name',
- component: () => import('../views/User.vue')
- },
- {
- name: 'notFound',
- path: '/:pathMatch(.*)',
- component: () => import('../views/NotFound.vue')
- }
- ];
- <template>
- <div>我是home组件div>
- <br />
-
- <router-link to="/home/a">toArouter-link>
- <br />
- <router-link to="/home/b">toBrouter-link>
-
- <br />
- <br />
-
- <router-view>router-view>
- template>


- <button @click="jumpClick('/home')">跳转到home组件button> |
- <button @click="jumpClick('/about')">跳转到about组件button>
-
-
- <script setup>
- // 1. 导入
- import { useRouter } from 'vue-router';
- // 2. 使用
- const router = useRouter();
-
- // 3. 监听点击
- const jumpClick = (url) => {
- // 传入 字符串
- router.push(url);
-
- // 传入 对象
- // router.push({
- // path: url
- // });
- };
- script>

- {
- name: 'home', // 用name这个属性来跳转
- path: '/home',
- component: () => import('../views/Home.vue'),
- meth: {
- name: 'coderstar',
- age: 28
- },
- children: [
- {
- path: '/home',
- redirect: '/home/A'
- },
- {
- path: 'a',
- component: () => import('../views/HomeA.vue')
- },
- {
- path: 'b',
- component: () => import('../views/HomeB.vue')
- }
- ]
- },
- {
- name: 'about', // 用name这个属性来跳转
- path: '/about',
- component: () => import('../views/About.vue')
- }
- <button @click="jumpClick('home')">跳转到home组件button> |
- <button @click="jumpClick('about')">跳转到about组件button>
-
- <script setup>
- // 1. 导入
- import { useRouter } from 'vue-router';
- // 2. 使用
- const router = useRouter();
- const jumpClick = (name) => {
- // 3. name跳转
- router.push({
- // name
- name: name,
- // 传递参数
- query: {
- message: '我是迪迦'
- }
- });
- };
- script>
- <template>
- <div>我是about组件div>
-
- {{ $route.query }}
- template>
-
- <script setup>
- import { onMounted } from 'vue';
- import { useRoute } from 'vue-router';
-
- const route = useRoute();
- onMounted(() => {
- // 2. js中获取
- console.log('获取到的参数', route.query);
- });
- script>

子路由的重定向路由会失效,看看上方home组件的即可知道
- {
- name: 'home',
- path: '/home', // 用path这个属性来跳转
- component: () => import('../views/Home.vue'),
- meth: {
- name: 'coderstar',
- age: 28
- },
- children: [
- {
- path: '/home',
- redirect: '/home/A'
- },
- {
- path: 'a',
- component: () => import('../views/HomeA.vue')
- },
- {
- path: 'b',
- component: () => import('../views/HomeB.vue')
- }
- ]
- },
- {
- name: 'about',
- path: '/about', // 用path这个属性来跳转
- component: () => import('../views/About.vue')
- },
- <button @click="jumpClick('/home')">跳转到home组件button> |
- <button @click="jumpClick('/about')">跳转到about组件button>
-
- <script setup>
- // 1. 导入
- import { useRouter } from 'vue-router';
- // 2. 使用
- const router = useRouter();
- const jumpClick = (url) => {
- // 3. path跳转
- router.push({
- // name
- path: url,
- // 传递参数
- query: {
- message: '迪迦变身!!!'
- }
- });
- };
- script>
- <template>
- <div>我是about组件div>
-
- {{ $route.query }}
- template>
-
- <script setup>
- import { onMounted } from 'vue';
- import { useRoute } from 'vue-router';
-
- const route = useRoute();
- onMounted(() => {
- // 2. js中获取
- console.log('获取到的参数', route.query);
- });
- script>

back => 想后回退
- <template>
- <div class="about">
- <h2>About: {{ $route.query }}h2>
- <button @click="backBtnClick">返回button>
- div>
- template>
-
- <script setup>
- import { useRouter } from 'vue-router'
- const router = useRouter()
-
- function backBtnClick() {
- router.back()
- }
- script>
forward => 想前进步
- <template>
- <div class="about">
- <h2>About: {{ $route.query }}h2>
- <button @click="backBtnClick">返回button>
- div>
- template>
-
- <script setup>
- import { useRouter } from 'vue-router'
- const router = useRouter()
- function backBtnClick() {
- router.forward()
- }
go => 可前进,可后退
- <template>
- <div class="about">
- <h2>About: {{ $route.query }}h2>
- <button @click="backBtnClick">返回button>
- div>
- template>
-
- <script setup>
- import { useRouter } from 'vue-router'
- const router = useRouter()
- function backBtnClick() {
- // go(1) -> forward()
- // go(-1) -> back()
- router.go(200)
- }
- script>
- <script setup>
- import { useRouter } from 'vue-router';
- const router = useRouter();
-
- const jumpClick = (url) => {
- // 跳转可以回溯
- router.push(url);
- };
- script>
- <script setup>
- import { useRouter } from 'vue-router';
- const router = useRouter();
-
- const jumpClick = (url) => {
- // 跳转不可回溯,没有记录
- router.replace(url)
- };
- script>
某些情况下可能需要动态的来添加路由
根据用户不同的权限,注册不同的路由
- // 添加顶层路由
- let isAdmin = true;
- if (isAdmin) {
- router.addRoute({
- name: 'admin',
- path: '/admin',
- component: () => import('../views/Admin.vue')
- });
- }
-
- // 5. 导出
- export default router;
- // 添加次级路由
- let isAdmin = true;
- if (isAdmin) {
- // 第一个参数传 父级的name
- router.addRoute('home', {
- name: 'home-a1',
- path: 'a1', // 实际上是 /home/a1
- component: () => import('../views/HomeA1.vue')
- });
- }
-
- // 5. 导出
- export default router;
- let isAdmin = true;
- if (isAdmin) {
- router.addRoute('home', {
- name: 'home-a1',
- path: 'a1',
- component: () => import('../views/HomeA1.vue')
- });
-
- // 三级路由,需要在 home-a1 中加上 router-view 哦
- router.addRoute('home-a1', {
- name: 'home-a2',
- path: 'a2', // 实际上是 /home/a1/a2
- component: () => import('../views/HomeA2.vue')
- });
- }
-
- // 5. 导出
- export default router;
添加一个name相同的路由
新添加的路由,会把之前同名的路由给覆盖掉,因为name属性是唯一的
- router.addRoute({
- name: 'home-a1',
- path: 'a1', // '/a1'
- component: () => import('../views/HomeA1.vue')
- });
-
- // 会覆盖掉上面的
- router.addRoute({
- name: 'home-a1',
- path: 'a999999', // '/a999999'
- component: () => import('../views/HomeA2.vue')
- });
通过removeRoute方法,传入路由的名称
- router.addRoute({
- name: 'home-a1',
- path: '/a1',
- component: () => import('../views/HomeA1.vue')
- });
-
- // 删除路由
- router.removeRoute('home-a1');
通过addRoute方法的返回值回调
- // 1. 增加路由后,会有一个返回值方法
- const removeA1 = router.addRoute({
- name: 'home-a1',
- path: '/a1',
- component: () => import('../views/HomeA1.vue')
- });
-
- // 2. 调用该返回值方法,即可删除路由
- removeA1();
router.hasRoute() => 检查路由是否存在
- console.log(router.hasRoute('about')); // true
-
- router.removeRoute('about');
-
- console.log(router.hasRoute('about')); // false
router.getRoutes():获取一个包含所有路由记录的数组
console.log(router.getRoutes()); // 一个路由数组

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航
全局的前置守卫 beforeEach 是在导航触发时会被回调的
进行任何的路由跳转之前, 传入的beforeEach中的函数都会被回调
- // 路由导航首位
- /**
- * to : 去哪个路由
- * from : 从哪里来
- */
-
- // 1. 设定需要登录才能进的页面
- const needLoginRoutePath = ['/about', '/user/222222/star'];
-
- router.beforeEach((to, from) => {
- // 2. 判断是否进入需要登录后才能进的页面
- if (needLoginRoutePath.includes(to.path)) {
- // 3. 获取登录状态
- const token = sessionStorage.getItem('token');
- // 4. 判断 => 如果没登录,跳转到登录页面
- if (!token) {
- // 01. 返回登录页面的路径即可
- // return '/login';
- // 02. 同时传递数据过去
- return {
- path: '/login',
- query: {
- toPath: to.path
- }
- };
- }
- }
- });
-
- // 5. 导出
- export default router;
- <template>
- <div>
- Login页面
- <br />
- 账号 : <input type="text" />
- <br />
- 密码 : <input type="password" />
- <br />
- <button @click="loginClick">登录button>
- div>
- template>
-
- <script setup>
- import { useRoute, useRouter } from 'vue-router';
-
- const route = useRoute();
- const router = useRouter();
-
- // 1. 监听登录按钮点击
- const loginClick = () => {
- // 2. 发送请求,进行登录
- // balabalbala~
- // 3. 存储token到sessionStorage
- sessionStorage.setItem('token', '冲啊,迪迦!!!!!!');
-
- console.log('我要去的页面', route.query.toPath);
- // 4. 跳转到指定页面
- router.push(route.query.toPath);
- };
- script>

