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 \…

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

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

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

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

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…

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…

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

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

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

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

修改默认时区,默认语言,默认国家

确认时区&#xff0c;语言&#xff0c;国家 build/make/target/product/languages_default.mkframeworks/base/packages/SettingsLib/res/xml/timezones.xml设备mk中添加相关内容 PRODUCT_PROPERTY_OVERRIDES \persist.sys.timezoneEurope/AmsterdamPRODUCT_PROPERTY_OVERRI…

前端vue用el-table如何实现表头内容过长换行处理,实现换行效果

前端vue用el-table如何实现表头内容过长换行处理&#xff0c;实现换行效果 这是效果图 有两种方法&#xff0c;一种简易版本&#xff0c;一种万能方法,都是el-table&#xff0c;先看文档 表头标题是可以自定义的 方法一 label的解释写在代码里面了&#xff0c;这里会自动形成换…

Python概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 了解Python Python&#xff0c;本义是指“蟒蛇”。1989年&#xff0c;荷兰人Guido van Rossum发明了一种面向对象的解释型高级编程语言&#xff0c;…

利用神经网络学习语言(六)——总结与常见面试问题

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 文章列表&#xff1a; 利用神经网络学习语言&#xff08;一&#xff09;——自然语言处理的基本要素利用神经网络学习语言&…

Java基础入门day49

day49 tomcat 启动 进入tomcat的bin目录&#xff0c;双击或者运行startup.bat文件启动tomcat 控制台最后出现服务器启动在多少毫米之内&#xff0c;代表服务器成功启动 org.apache.catalina.startup.Catalina.start Server startup in 405 ms 验证tomcat 在浏览器中输入 loca…

[算法] 优先算法(二): 双指针算法(下)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

基于transformers框架实践Bert系列6-完形填空

本系列用于Bert模型实践实际场景&#xff0c;分别包括分类器、命名实体识别、选择题、文本摘要等等。&#xff08;关于Bert的结构和详细这里就不做讲解&#xff0c;但了解Bert的基本结构是做实践的基础&#xff0c;因此看本系列之前&#xff0c;最好了解一下transformers和Bert…

Python筑基之旅-MySQL数据库(一)

目录 一、MySQL数据库 1、简介 2、优点 2-1、开源和免费 2-2、高性能 2-3、可扩展性 2-4、易用性 2-5、灵活性 2-6、安全性和稳定性 2-7、丰富的功能 2-8、结合其他工具和服务 2-9、良好的兼容性和移植性 3、缺点 3-1、对大数据的支持有限 3-2、缺乏全文…