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.pswp.cn/diannao/13541.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13541.shtml
英文地址,請注明出處:http://en.pswp.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;獲取…