vite+ts+mock+vue-router+pinia实现vue的路由权限

0.权限管理

前端的权限管理主要分为如下:

  • 接口权限
  • 路由权限
  • 菜单权限
  • 按钮权限

权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源

1.项目搭建

创建vite项目

yarn create vite

配置别名

npm install path --savenpm install @types/node --save-dev

tsconfig.json
在这里插入图片描述

    "baseUrl": ".","paths": {"@/*": ["src/*"],"@components/*": ["./src/components/*"]},

vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from "path";// https://vitejs.dev/config/
export default defineConfig({resolve: {// 配置路径别名alias: {"@": path.resolve(__dirname, "./src"),"@components": path.resolve(__dirname, "./src/components"),},},plugins: [vue(),]})

创建基础路由

npm i vue-router@4
const routes = [{name: "Home",path: "/",component: () => import("@/views/Home.vue"),},];export default routes; //导出
import { createRouter, createWebHistory } from "vue-router";
import routes from "./router";const router = createRouter({history: createWebHistory(),routes,
});
export default router;
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
const app =createApp(App)
app.use(router)
app.mount('#app')
<script setup lang="ts">
</script><template><router-view></router-view>
</template><style scoped></style>

配置mock

yarn add mockjs vite-plugin-mock -D
import { MockMethod } from 'vite-plugin-mock';
export default [{url: `/api/list`,method: 'get',response: () => {return [{name:'tom',age:16,nation:'USA'}];},},] as MockMethod[];

vite.config.ts配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import { viteMockServe } from 'vite-plugin-mock'// https://vitejs.dev/config/
export default defineConfig({resolve: {// 配置路径别名alias: {"@": path.resolve(__dirname, "./src"),"@components": path.resolve(__dirname, "./src/components"),},},plugins: [vue(),viteMockServe({mockPath: './src/mock'})]
})

使用

<script setup lang="ts">
import axios from 'axios';axios.get('/api/list').then(res=>{console.log(res.data);})
</script><template>
<h1>超市管理系统首页</h1></template><style scoped></style>

在这里插入图片描述

安装pinia

yarn add pinia
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
const pinia = createPinia()const app =createApp(App)
app.use(router)
app.use(pinia)
app.mount('#app')
import { defineStore } from 'pinia'export const useMarkStore = defineStore('mark', {state: () => ({ count: 0 }),getters: {double: (state) => state.count * 2,},actions: {increment() {this.count++},},
})
<script setup lang="ts">
import { useMarkStore } from '@/store/store';
import axios from 'axios';const store= useMarkStore()
axios.get('/api/list').then(res=>{console.log(res.data);})
</script><template>
<h1>超市管理系统首页</h1>
<h1>{{ store.count }}</h1></template><style scoped></style>

在这里插入图片描述

安装js-cookie插件

yarn add js-cookie

2.路由权限(包括菜单权限和按钮权限)

目录结构:
在这里插入图片描述

mock

import { MockMethod } from "vite-plugin-mock";
export default [{url: `/api/list`,method: "post",response: ({ body }) => {return body;},},{url: `/api/login`, //登录逻辑method: "post",response: ({ body }) => {let data = {};if (body.username == "tom") {data = {id: "1111",token: "4566adasdqfrqwd",};} else if (body.username == "amy") {data = {id: "222",token: "45184adaczz52za",};}return data;},},{url: `/api/getRoutes`, //简单方案:根据用户返回不同路由,真实后端逻辑:根据登录用户的角色去表里查授权该角色的的菜单method: "post",response: ({ body }) => {console.log(body);const routes = [];if (body.id == "1111") {routes.push({name: "page1",path: "/page1",component: "/Page1.vue",},{name: "page2",path: "/page2",component: "/Page2.vue",});} else if (body.id == "222") {routes.push( {name: "page3",path: "/page3",component: "/Page3.vue",});}return routes;},},
] as MockMethod[];

router

在这里插入图片描述

store

import { defineStore } from "pinia";
import Cookies from "js-cookie";
import axios from "axios";
import routes from '@/router/router'
const modules = import.meta.glob("../views/**/*.vue");export const useMarkStore = defineStore("mark", {state: () => ({pageRoutes: <any>[], //当前页面缓存路由asyncRoutes: <any>[],//从接口获取到的路由数组}),getters: {},actions: {SET_ROUTES(_routes: any[]){//设置state中的值this.$state.asyncRoutes=_routesthis.$state.pageRoutes=routes.concat(_routes)},getRouter() {//从后端接口获取到动态路由let _id = Cookies.get("id");if (_id) {return new Promise((resolve, reject) => {axios.post("/api/getRoutes", { id: _id }).then((res) => {console.log(res);let _data = res.data;let newData = this.parseRouter(_data);this.SET_ROUTES(newData)resolve(newData);});});}},parseRouter(_data: Array<any>) {//处理后端返回的路由数据=》vite项目能解析的路由格式let _newArr: Array<any> = [];_data.forEach((item: any) => {let newItem = Object.assign({}, item);let comp = item.component;newItem.component = modules[`../views${comp}`];_newArr.push(newItem);});return _newArr;},},getButtonCode(){//按钮权限思路://1.在登录的时候拉取按钮权限编码code['EXPORT_LIST','OPEN_MODAL']//2.将编码缓存本地//3.页面通过v-if控制按钮或是自义定指令控制按钮}
});

permission.ts

import router from "@/router";
import { useMarkStore } from "@/store/store";
import Cookies from "js-cookie";//获取view下所有的vue文件
// const modules = import.meta.glob('../views/**/*.vue')//   export const getCurrRoutes=(name:string)=>{//   }// await axios.post('/api/getRoutes',{username:'tom'}).then(res=>{
//     console.log(res);
//     let _data=res.data
//     _data.forEach((item:any)=>{
//         let newItem=Object.assign({},item)
//         let comp=item.component//         newItem.component=modules[`../views${comp}`]
//         router.addRoute(newItem)
//     })// })
//白名单
const whiteList=['/about','/new','/login']//路由守卫
router.beforeEach(async(to,from,next)=>{const store= useMarkStore()const token=Cookies.get("token")console.log(token);if(token){if(to.path=='login'){next('/')}else{//判断是否拿了路由规则if(store.asyncRoutes.length==0){//格式化好的路由const _temp:any=  await store.getRouter()_temp.forEach((item:any)=>router.addRoute(item))//继续跳转next(to.path)}else{if(to.matched.length!=0){next()}else{alert('无页面权限')next(from.path)}}}}else{if(whiteList.indexOf(to.path)!= -1){next()}else{next('/login')}}
})

Login.vue

<script setup lang="ts">
import axios from 'axios';
import { ref } from 'vue';
import Cookies from 'js-cookie'
import { useRouter } from 'vue-router';
const router =useRouter()
const username=ref()const login=()=>{axios.post('/api/login',{username:username.value}).then(res=>{console.log(res);if(res.data.token){Cookies.set('token',res.data.token)Cookies.set('id',res.data.id)router.push('/')}})  axios.post('/api/getRoutes',{username:username.value}).then(res=>{console.log(res);})
}
</script><template>
<h1>登录</h1>
<div>用户名:<input type="text" v-model="username"></div>
<button @click="login">登录</button></template><style scoped></style>

Home.vue

<script setup lang="ts">
import { useMarkStore } from '@/store/store';
import axios from 'axios';
import Cookies from 'js-cookie'const store= useMarkStore()
axios.post('/api/list',{params:{name:'aaa'}}).then(res=>{console.log(res);})import { useRouter } from 'vue-router';
const router =useRouter()
const loginout=()=>{Cookies.remove('token')Cookies.remove('id')router.push('/login')
}</script><template><div @click="loginout">登出</div>
<h1>超市管理系统首页</h1>
<div>当前用户{{  }}</div>
<div>当前用户可用菜单:</div>
<div v-if="store.asyncRoutes" style="display: flex;flex-direction: column;" ><a v-for="item in store.asyncRoutes" :href="item.path">{{ item?.name }}</a>
</div></template><style scoped></style>

main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import  '@/util/permission'
const pinia = createPinia()const app =createApp(App)
app.use(router)
app.use(pinia)
app.mount('#app')

按钮权限思路

 getButtonCode(){//按钮权限思路://1.在登录的时候拉取按钮权限编码code['EXPORT_LIST','OPEN_MODAL']//2.将编码缓存本地//3.页面通过v-if控制按钮或是自义定指令控制按钮}

前端控制权限

//1.在路由配置中配置白名单
{name: "Login",path: "/login",component: () => import("@/views/Login.vue"),meta:{whiteList:['admin','tom']}},//2.在路由守卫beforeEach中判断当前用户角色是否在meta中,是就next()

效果

在这里插入图片描述
tom登录
在这里插入图片描述
amy登录

在这里插入图片描述

3.接口权限

登录完拿到token,将token存起来,通过axios请求拦截器进行拦截,每次请求的时候头部携带token

axios.interceptors.request.use(config => {config.headers['token'] = cookie.get('token')return config
})
axios.interceptors.response.use(res=>{},{response}=>{if (response.data.code === 40099 || response.data.code === 40098) { //token过期或者错误router.push('/login')}
})

4.注意点

mock


const login=()=>{//这里传参有三种方式:data,params,{}axios.post('/api/login',{username:'tom'}).then(res=>{console.log(res);}) 
import { MockMethod } from "vite-plugin-mock";
export default [{url: `/api/login`, //登录逻辑method: "post",response: ({ body }) => {//获取传的参数使用bodyreturn body;},},] as MockMethod[];

addRoute

动态添加路由在vite中不能使用以下方法:

// 路由拼接
function loadView(view:string) {return () => import(`@/views/${view}`)
}

上面的代码会报错:TypeError: Failed to resolve module specifier,应该采用import.meta.glob方式

import router from "@/router";
import axios from "axios";
//获取view下所有的vue文件
const modules = import.meta.glob('../views/**/*.vue')//这里需要将异步获取的值改为同步
await axios.post('/api/getRoutes',{username:'tom'}).then(res=>{console.log(res);let _data=res.data_data.forEach((item:any)=>{let newItem=Object.assign({},item)let comp=item.componentnewItem.component=modules[`../views${comp}`]router.addRoute(newItem)})})

5.源码地址

https://gitee.com/beekim/vue-route-mgr

参考:
https://cloud.tencent.com/developer/article/1794300
https://github.com/vitejs/vite/discussions/2746
https://blog.csdn.net/lucklymm/article/details/125420877
https://blog.csdn.net/weixin_43239880/article/details/129922664
https://blog.csdn.net/qq_36651686/article/details/116520731

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

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

相关文章

4. C++入门:内联函数、auto关键字、范围for及nullptr

内联函数 概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率 对比C的宏 C语言不足&#xff1a;宏 #define ADD(x, y) ((x)(y))int main() {int ret…

python实现520表白图案

今天是520哦&#xff0c;作为程序员有必要通过自己的专业知识来向你的爱人表达下你的爱意。那么python中怎么实现绘制520表白图案呢&#xff1f;这里给出方法&#xff1a; 1、使用图形库&#xff08;如turtle&#xff09; 使用turtle模块&#xff0c;你可以绘制各种形状和图案…

Docker 安装kingbase V8r6

下载 官网下载&#xff0c;注意&#xff1a;这里下载 Docker 版本v8r6 安装 # 导入镜像 docker load -i kingbase.tar# 重命名 docker tag [image-name]:[tag] [new-image-name]:[new-tag]# 删除 docker rmi [image-name]:[tag]# 创建容器 docker run -tid \ --privileged \…

python实现绘制烟花代码

在Python中&#xff0c;我们可以使用多个库来绘制烟花效果&#xff0c;例如turtle库用于简单的绘图&#xff0c;或者更复杂的库如pygame或matplotlib结合动画。但是&#xff0c;由于turtle库是Python自带的&#xff0c;我们可以使用它来绘制一个简单的烟花效果。 下面是一个使…

Stable Diffusion AMD加速方法-ZLUDA重出江湖

目前几大开源的Stable Diffusion平台&#xff0c;更新速度都慢了&#xff0c;一个是没有太多新技术出现&#xff0c;新出的基础模型也都不完整开源了&#xff08;API调用&#xff09;&#xff0c;能整的功能&#xff0c;也都整得差不多了。然后一群AMD死忠还在等着有一个能有一…

【前端】使用 Canvas 实现贪吃蛇小游戏

使用 Canvas 实现贪吃蛇小游戏 在这篇博客中&#xff0c;我们将介绍如何使用 HTML5 Canvas 和 JavaScript 实现一个简单的贪吃蛇&#xff08;Snake&#xff09;小游戏。这个项目是一个基础的游戏开发练习&#xff0c;它可以帮助你理解如何在 Canvas 上绘图、如何处理用户输入以…

Laravel(Lumen8) + Supervisor 实现多进程redis消息队列

相关文章:Supervisor守护进程工具安装与使用 1、通用消息队列 /App/Job/CommonJob.php: <?phpnamespace App\Jobs; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str;class CommonJob extends Job {public $timeout; //超时时间protected $data; //队列…

Android:OkHttp网络请求框架的使用

目录 一&#xff0c;OkHttp简介 二&#xff0c;OkHttp请求处理流程 三&#xff0c;OkHttp环境配置 四&#xff0c;OkHttp的使用 1.get网络请求 2.post上传表单数据 3.post上传json格式数据 4.文件上传 5.文件下载 一&#xff0c;OkHttp简介 OkHttp是square公司推出的一…

npm 源管理工具 nrm

npm 源管理工具 nrm 安装(可能很慢, 多试几次) npm install -g nrm查看可选择源列表 nrm ls切换源 nrm use <registry>如: nrm use taobao

rust的版本问题,安装问题,下载问题

rust的版本、安装、下载问题 rust版本问题&#xff0c; 在使用rust的时候&#xff0c;应用rust的包&#xff0c;有时候包的使用和rust版本有关系。 error: failed to run custom build command for pear_codegen v0.1.2 Caused by: process didnt exit successfully: D:\rus…

鸿蒙全面开发指南:入门、生态安全与资源支持

鸿蒙全面开发指南&#xff1a;入门、生态安全与资源支持 本文全面梳理了鸿蒙操作系统的开发入门流程&#xff0c;涵盖了开发环境准备、工具使用、项目创建、模拟器配置到应用安全设计的各个方面。通过本文&#xff0c;读者不仅能够了解鸿蒙开发的基本步骤&#xff0c;也能深入理…

Aspose.PDF功能演示:在 JavaScript 中将 TXT 转换为 PDF

您是否正在寻找一种在 JavaScript 项目中将纯文本文件从TXT无缝转换为PDF格式的方法&#xff1f;您来对地方了&#xff01;无论您是要构建 Web 应用程序、创建生产力工具&#xff0c;还是只是希望简化工作流程&#xff0c;直接从 JavaScript 代码中将 TXT 转换为 PDF 的功能都可…

第3天 Web源码拓展_小迪网络安全笔记

1.关于web源码目录结构 #数据库配置文件 后台目录 模板目录 数据库目录 1.1数据库配置文件: 1.1就拿wordpress来说,先到官网下载源码:Download – WordPress.org,解压源码之后: 2.2找到目录下名为 wp-config-sample.php的文件,这就是数据库配置文件: 设想: 我们在渗透…

FOURIER NEURAL OPERATOR FOR PARAMETRIC PARTIAL DIFFERENTIAL EQUATIONS

参数偏微分方程的傅里叶神经算子 论文链接&#xff1a;https://arxiv.org/abs/2010.08895 项目链接&#xff1a;https://github.com/neuraloperator/neuraloperator 作者博客&#xff1a;https://zongyi-li.github.io/blog/2020/fourier-pde/ 参数偏微分方程的傅里叶神经算子…

本地部署Terraria泰拉瑞亚私服并通过内网穿透生成公网地址远程联机

文章目录 前言1. 下载Terraria私服2. 本地运行Terraria 私服3. 本地Terraria私服连接4. Windwos安装Cpolar 工具5. 配置Terraria远程联机地址6. Terraria私服远程联机7. 固定远程联机地址8. 固定的联机地址测试 前言 本文将为你详细介绍在本地如何运行泰拉瑞亚本地私服和结合C…

认识 React Hooks

回顾函数组件 函数组件 没有组件实例 不能监听各个生命周期 无法扩展属性和方法 没有 state 和 setState 只是输入 props &#xff0c;输出 jsx &#xff0c;纯函数。 // class 组件class List extends React.Component {constructor(props) {super(props)}render() {con…

信息泄露--注意点点

目录 明确目标: 信息泄露: 版本软件 敏感文件 配置错误 url基于文件: url基于路由: 状态码: http头信息泄露 报错信息泄露 页面信息泄露 robots.txt敏感信息泄露 .get文件泄露 --判断: 搜索引擎收录泄露 BP: 爆破: 明确目标: 失能 读取 写入 执行 信息泄…

【文末附gpt升级方案】Ilya离开OpenAI内幕探究:算力削减与商业优先策略的冲突

Ilya离开OpenAI内幕探究&#xff1a;算力削减与商业优先策略的冲突 一、引言 在人工智能&#xff08;AI&#xff09;领域的飞速发展中&#xff0c;OpenAI一直以其领先的技术和创新产品而备受瞩目。然而&#xff0c;近日发生的Ilya Sutskever离开OpenAI的事件却引起了业界的广…

java企业级云MES系统全套源码,支持app、小程序、H5、台后管理

企业级云MES全套源码&#xff0c;支持app、小程序、H5、台后管理端 企业级智能制造MES系统源码&#xff0c;技术架构&#xff1a;springboot vue-element-plus-admin MES指的是制造企业生产过程执行系统&#xff0c;是一套面向制造企业车间执行层的生产信息化管理系统。MES可以…

栈(基于动态顺序表实现的栈)

栈的简单介绍 关于栈的性质咳咳 栈&#xff1a;栈是一种特殊的线性表,其中只让在一端插入和删除元素。 后进先出 进行插入删除的那一端叫栈顶&#xff0c;另一端叫栈底 我们实现的栈是基于一个动态顺序表的的栈&#xff0c;会实现栈的 入栈&#xff0c;出栈&#xff0c;获取…