vue3-10

动态路由与菜单
路由文件

a6router.ts

import { createRouter, createWebHashHistory } from "vue-router";
import { useStorage } from "@vueuse/core";
import { Route, Menu } from "../model/Model8080";
const clientRoutes = [{path: "/login",name: "login",component: () => import("../views/A6Login.vue"),},{path: "/404",name: "404",component: () => import("../views/A6NotFound.vue"),},{path: "/",name: "main",component: () => import("../views/A6Main.vue"),},{path: "/:pathMatcher(.*)*",name: "remaining",redirect: "/404",},
];const router = createRouter({history: createWebHashHistory(),routes: clientRoutes,
});export const serverMenus = useStorage<Menu[]>("serverMenus", []);
const serverRoutes = useStorage<Route[]>("serverRoutes", []);
addServerRoutes(serverRoutes.value);export function addServerRoutes(routeList: Route[]) {for (const r of routeList) {if (r.parentName) {router.addRoute(r.parentName, {path: r.path,component: () => import(r.component),name: r.name,});}}serverRoutes.value = routeList;
}export function resetRoutes() {for (const r of clientRoutes) {router.addRoute(r);}serverRoutes.value = null;serverMenus.value = null;
}export default router;
export interface Route {path: string;component: string;name: string;parentName: string;
}export interface Menu {id: number;pid: number;title: string;icon?: string;routePath?: string;routeComponent?: string;routeName?: string;routeParentName?: string;children?: Menu[];
}

本文件重要的函数及变量

  • addServerRoutes 函数向路由表中添加由服务器提供的路由,路由分成两部分

    • clientRoutes 这是客户端固定的路由

    • serverRoutes 这是服务器变化的路由,存储于 localStorage

  • resetRoutes 函数用来将路由重置为 clientRoutes

    • vue-router@4 中的 addRoute 方法会【覆盖】同名路由,这是这种实现的关键

    • 因此,服务器返回的路由最好是 main 的子路由,这样重置时就会比较简单,用之前的 main 一覆盖就完事了

  • serverMenus 变量记录服务器变化的菜单,存储于 localStorage

  • 登录组件

    动态路由应当在登录时生成,A6Login.vue

    <template><div class="login"><a-form :label-col="{ span: 6 }" autocomplete="off"><a-form-item label="用户名" v-bind="validateInfos.username"><a-input v-model:value="dto.username" /></a-form-item><a-form-item label="密码" v-bind="validateInfos.password"><a-input-password v-model:value="dto.password" /></a-form-item><a-form-item :wrapper-col="{ offset: 6, span: 16 }"><a-button type="primary" @click="onClick">Submit</a-button></a-form-item></a-form></div>
    </template>
    <script setup lang="ts">
    import { ref, onMounted } from 'vue'
    import { Form } from 'ant-design-vue'
    import { useRouter } from 'vue-router'
    import axios from '../api/request'
    import { useRequest } from 'vue-request'
    import { AxiosRespToken, LoginDto, AxiosRespMenuAndRoute } from '../model/Model8080'
    import { resetRoutes, addServerRoutes, serverMenus } from '../router/a6router'
    const dto = ref({username:'', password:''})
    const rules = ref({username: [{required: true, message:'用户名必填'}],password:[{required: true, message:'密码必填'}]
    })
    const { validateInfos, validate } = Form.useForm(dto, rules)
    const router = useRouter()
    const { runAsync:login } = useRequest<AxiosRespToken, LoginDto[]>((dto)=> axios.post('/api/loginJwt', dto), {manual:true})
    const { runAsync:menu } = useRequest<AxiosRespMenuAndRoute, string[]>((username)=> axios.get(`/api/menu/${username}`), {manual:true})
    async function onClick() {try {await validate()const loginResp = await login(dto.valueif(loginResp.data.code === 200) { // 登录成功const token = loginResp.data.data.tokenconst menuResp = await menu(dto.value.username)const routeList = menuResp.data.data.routeListaddServerRoutes(routeList)serverMenus.value = menuResp.data.data.menuTreerouter.push('/')})} catch (e) {console.error(e)}
    }
    onMounted(()=>{resetRoutes()
    })
    </script>
    <style scoped>
    .login {margin: 200px auto;width: 25%;padding: 20px;height: 180px;background-color: antiquewhite;
    }
    </style>
    
  • 登录成功后去请求 /api/menu/{username} 获取该用户的菜单和路由

  • router.push 方法用来以编程方式跳转至主页路由

主页组件

A6Main.vue

<template><div class="a6main"><a-layout><a-layout-header> </a-layout-header><a-layout><a-layout-sider><a-menu mode="inline" theme="dark"><template v-for="m1 of serverMenus"><a-sub-menu v-if="m1.children" :key="m1.id" :title="m1.title"><template #icon><a-icon :icon="m1.icon"></a-icon></template><a-menu-item v-for="m2 of m1.children" :key="m2.id"><template #icon><a-icon :icon="m2.icon"></a-icon></template><router-link v-if="m2.routePath" :to="m2.routePath">{{m2.title}}</router-link><span v-else>{{ m2.title }}</span></a-menu-item></a-sub-menu><a-menu-item v-else :key="m1.id"><template #icon><a-icon :icon="m1.icon"></a-icon></template><router-link v-if="m1.routePath" :to="m1.routePath">{{m1.title}}</router-link><span v-else>{{ m1.title }}</span></a-menu-item></template></a-menu></a-layout-sider><a-layout-content><router-view></router-view></a-layout-content></a-layout></a-layout></div>
</template>
<script setup lang="ts">
import AIcon from "../components/AIcon3"; // jsx icon 组件
import { serverMenus } from "../router/a6router";
</script>
<style scoped>
.a6main {height: 100%;background-color: rgb(220, 225, 255);box-sizing: border-box;
}
.ant-layout-header {height: 50px;background-color: darkseagreen;
}.ant-layout-sider {background-color: lightsalmon;
}.ant-layout-content {background-color: aliceblue;
}.ant-layout-footer {background-color: darkslateblue;height: 30px;
}.ant-layout {height: 100%;
}.ant-layout-has-sider {height: calc(100% - 50px);
}
</style>

token 使用
  1. 获取用户信息,例如服务器端可以把用户名、该用户的路由、菜单信息都统一从 token 返回

  2. 前端路由跳转依据,例如跳转前检查 token,如果不存在,表示未登录,就避免跳转至某些路由

  3. 后端 API 访问依据,例如每次发请求携带 token,后端需要身份校验的 API 需要用到

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/171916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx的一些命令

linux start nginx 开启 /usr/sbin/nginx&#xff08;直接启动&#xff09; nginx -s stop 停止 /usr/local/nginx/sbin/nginx -s stop nginx -s quit 安全停止&#xff0c;保存信息 nginx -s reload 当配置信息修改&#xff0c;需要重新载入这些配置时使用此命令 nginx -s re…

MATLAB|交叉折线图之间分色填充

目录 公众号 效果图 交叉折线图之间分色填充概念介绍 应用领域 优点 缺点

Linux内核--内存管理(二)物理内存分页机制

一、引言 二、物理内存模型 ------>2.1、平坦内存模型(Flat Memory Model) ------>2.2、对称多处理 SMP(Symmetric MultiProcessing) ------>2.3、非均衡访存模型 NUMA(Non-Uniform Memory Access) 三、节点、区域和页 ------>3.1、节点 ------>3.2、区域…

Python 安装mysqlclient 错误 无法打开包括文件: “mysql.h”: 解决方法

解决方案&#xff1a;python最新3.12.0不支持mysqlclient 请下载 python3.9.9 版本 高速下载地址CNPM Binaries Mirror 官方下载地址Welcome to Python.org 下载完成后将python添加到环境变量 pycharm 虚拟环境下的python版本切换到你刚才下载的3.9.9的python版本 Avai…

C#文件操作File类vsFileInfo类和Directory类vsDirectoryInfo类

目录 一、File类vsFileInfo类 1.File类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 2.FileInfo类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 二、 Directory类vsDirectoryInfo类 1.Directory类 &#xff08;…

FilterChain攻击解析及利用

文章目录 BASE64解码和编码原理浅析EncodingDecoding Filterchain构造&#xff08;原理阐述&#xff09;回顾死亡代码特性一&#xff08;双重去杂&#xff09;特性二&#xff08;粘合性&#xff09; 任意字符构造工具一工具二 实战例题[NSSRound#7 Team]brokenFilterChain&…

运维01:云计算

云计算的类型 分类&#xff1a;公有云、私有云、混合云 云计算的服务模式 服务模式分3种&#xff1a; ①IaaS&#xff08;Infrastructure as a Service&#xff09;&#xff1a;基础设施即服务 ②PaaS&#xff08;Platform as a Service&#xff09;&#xff1a;平台即服务…

Java并发编程

一、基础知识 1. 为什么要使用并发编程 提升多核CPU的利用率&#xff1a;一般来说一台主机上的会有多个CPU核心&#xff0c;我们可以创建多个线程&#xff0c;理论上讲操作系统可以将多个线程分配给不同的CPU去执行&#xff0c;每个CPU执行一个线程&#xff0c;这样就提高了CP…

Portraiture2024最新Photoshop磨皮插件更新啦

Portraiture是一款由Imagenomic公司研发的Photoshop磨皮插件。该插件以其优秀的磨皮效果&#xff0c;成为了众多摄影师和化妆师使用的首选插件。Portraiture主要用于影楼、婚纱、时尚摄影等各个领域。其主要特点是能够轻松地模拟人眼的视觉感受&#xff0c;自然地修饰人像照片。…

带头双向循环链表的实现

目录 认识带头双向循环链表 双向链表 循环链表 带头链表 带头双向循环链表 双向链表的优势和不足&#xff1a; 顺序表的优势和不足&#xff1a; 实现带头双向循环链表 创建带头双向循环链表 初始化 创建返回链表的头结点 打印链表 尾插 尾删 头插 头删 查找 在…

java小游戏之【王者荣耀】

首先创建一个新的Java项目命名为“王者荣耀”&#xff0c;并在src下创建两个包分别命名为“com.sxt"、”com.stx.beast",在相应的包中创建所需的类。 代码 package com.sxt;import javax.swing.*; import java.awt.*;public class Background extends GameObject {p…

android shape绘制半圆

<?xml version"1.0" encoding"utf-8"?><shape xmlns:android"http://schemas.android.com/apk/res/android"android:shape"rectangle"><sizeandroid:width"20dp"android:height"10dp" /><…

滑块验证码之模拟人工滑速

前言 代码直接运行即可 此处是用的selenium模拟&#xff0c;主要记录的难点是如何 模拟人工滑速 具体原理和利用到的东西都有做注释&#xff0c;逻辑完整&#xff0c;小白还是可以尝试理解的 一、正常简单模拟滑动 目标网址&#xff1a;点击 import base64 import time im…

【全栈开发】RedwoodJS与BlitzJS:全栈JavaScript元框架的未来

Redwood和Blitz是两个即将出现的全栈元框架&#xff0c;它们提供了创建SPAs、服务器端渲染页面和静态生成内容的工具&#xff0c;并提供了生成端到端支架的CLI。我一直在等待一个有价值的Rails JavaScript替代品&#xff0c;谁知道什么时候。这篇文章是对两者的概述&#xff0c…

参数估计(三)区间估计

文章目录 区间估计的概念一个正态总体的情形 μ \mu μ 的区间估计 σ 2 \sigma^2 σ2 的区间估计 两个正态总体的情形 μ 1 − μ 2 \mu_1-\mu_2 μ1​−μ2​ 的区间估计 σ 1 2 / σ 2 2 \sigma_1^2/\sigma_2^2 σ12​/σ22​ 的区间估计 参考文献 区间估计的概念 对未知参…

opencv-利用DeepLabV3+模型进行图像分割去除输入图像的背景

分离图像中的人物和背景通常需要一些先进的图像分割技术。GrabCut是一种常见的方法&#xff0c;但是对于更复杂的场景&#xff0c;可能需要使用深度学习模型。以下是使用深度学习模型&#xff08;如人像分割模型&#xff09;的示例代码&#xff1a; #导入相关的库 import cv2 …

[C++]指针与结构体

标题 一.指针1.指针的定义和使用2.指针所占的内存空间3.空指针与野指针4.const修饰指针5.指针和数组6.指针和函数 二.结构体1.结构体的定义与使用2.结构体数组3.结构体指针4.结构体的嵌套使用5.结构体做函数参数6.结构体中const使用场景7.案例练习 一.指针 作用: 可以通过指针…

FPGA驱动CS4344 VHDL例程

CS4344是一款非常简单的I2S立体声24bit D/A芯片&#xff0c;采样率高达192KHz&#xff0c;相对于ADAU1761复杂的寄存器配置来说&#xff0c;CS4344非常友好&#xff0c;无需配置寄存器&#xff0c;只要按I2S时序输入数据&#xff0c;即可实现立体声输出&#xff0c;且10PIN TSS…

SpringBoot 拦截器高级篇

Springboot 拦截器 定义使用场景拦截器与过滤器的区别实现步骤全局拦截器的局限性全局拦截器VS局部拦截器局部拦截器自定义局部拦截器使用多个局部拦截器 定义 拦截器是Spring MVC框架中的一个重要组件&#xff0c;它是一种AOP&#xff08;面向切面编程&#xff09;的实现方式&…

探索计算机视觉:深度学习与图像识别的融合

探索计算机视觉&#xff1a;深度学习与图像识别的融合 摘 要&#xff1a; 本文将探讨计算机视觉领域中的深度学习技术&#xff0c;并重点关注图像识别方面的应用。我们将介绍卷积神经网络&#xff08;CNN&#xff09;的原理、常用的图像数据集以及图像识别的实际应用场景&…