vue3+vit+vue-router路由,側邊欄菜單,面包屑導航設置層級結構

文章目錄

  • 注意
  • 效果圖
  • 目錄結構
  • 代碼
    • vite.config.ts需要配置路徑別名@符號
    • main.ts
    • App.vue
    • Breadcrumb.vue面包屑組件
    • menus.ts
    • // src/router/index.ts
    • 其他文件

注意

  • 目錄結構僅供參考
  • DefaultLayout.vue 沒有用到,我直接寫在APP文件中
  • vux-store我也沒有用到,單獨寫了一個配置文件存儲菜單數據
  • 詳細代碼需要參考后面貼出來的實際代碼

效果圖

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

目錄結構

src/
├── views/
│   ├── user/                     # 用戶管理模塊
│   │   ├── UserList.vue          # 用戶列表頁面(主頁面)
│   │   ├── UserDetails.vue       # 用戶詳情頁面(子頁面)
│   │   ├── UserEdit.vue          # 用戶編輯頁面(子頁面)
│   │   └── UserSettings.vue      # 用戶設置頁面(子頁面)
│   │
│   ├── role/                     # 用戶角色管理模塊
│   │   └── UserRole.vue          # 用戶角色管理頁面
│   │
│   ├── permission/               # 權限管理模塊
│   │   ├── PermissionList.vue    # 權限列表頁面(主頁面)
│   │   ├── PermissionAdd.vue     # 權限添加頁面(子頁面)
│   │   └── PermissionSetting.vue # 權限設置頁面(子頁面)
│   │
│   └── layout/                   # 布局組件
│       └── DefaultLayout.vue (沒有)    # 主布局,包含菜單和面包屑導航
│
├── router/
│   └── index.js                  # 路由配置文件
│
├── store/
│   └── modules/
│       └── menu.js  (沒有)             # 動態菜單狀態管理
│
└── components/└── breadcrumb/               # 面包屑組件└── Breadcrumb.vue
用戶管理└── 用戶列表(含詳情、編輯)└── 用戶角色管理└── 用戶設置└── 偏好設置(有編輯頁)└── 安全設置(有修改頁)
src/
├── pages/
│   ├── user/
│   │   ├── UserList.vue
│   │   ├── UserDetails.vue
│   │   ├── UserEdit.vue
│   │   ├── UserSettings.vue         # 用戶設置主頁面
│   │   ├── preferences/
│   │   │   ├── PreferenceSettings.vue  # 偏好設置頁面
│   │   │   └── PreferenceEdit.vue      # 偏好編輯頁面
│   │   └── security/
│   │       ├── SecuritySettings.vue    # 安全設置頁面
│   │       └── SecurityModify.vue      # 安全修改頁面
│   ├── role/
│   │   └── UserRole.vue
│   └── permission/
│       └── ...

代碼

vite.config.ts需要配置路徑別名@符號

import path from 'node:path'
import Vue from '@vitejs/plugin-vue'import Unocss from 'unocss/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
import VueRouter from 'unplugin-vue-router/vite'import { defineConfig } from 'vite'// https://vitejs.dev/config/
export default defineConfig({resolve: {alias: {'@/': `${path.resolve(__dirname, 'src')}/`,},},css: {preprocessorOptions: {scss: {additionalData: `@use "@/styles/element/index.scss" as *;`,api: 'modern-compiler',},},},plugins: [Vue(),// https://github.com/posva/unplugin-vue-routerVueRouter({extensions: ['.vue', '.md'],dts: 'src/typed-router.d.ts',}),Components({// allow auto load markdown components under `./src/components/`extensions: ['vue', 'md'],// allow auto import and register components used in markdowninclude: [/\.vue$/, /\.vue\?vue/, /\.md$/],resolvers: [ElementPlusResolver({importStyle: 'sass',}),],dts: 'src/components.d.ts',}),// https://github.com/antfu/unocss// see uno.config.ts for configUnocss(),],ssr: {// TODO: workaround until they support native ESMnoExternal: ['element-plus'],},
})

main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import '@/styles/index.scss'
import 'uno.css'// If you want to use ElMessage, import it.
import 'element-plus/theme-chalk/src/message.scss'
import 'element-plus/theme-chalk/src/message-box.scss'const app = createApp(App)app.use(router)
app.use(ElementPlus)app.mount('#app')

App.vue

<!-- src/App.vue -->
<template><el-container class="layout-container"><!-- 左側側邊欄 --><el-aside width="200px" class="layout-aside"><el-menudefault-active="$route.path"routerclass="side-menu"background-color="#ffffff"text-color="#333"active-text-color="#409EFF"><!-- 動態生成菜單 --><div v-for="menu in menus" :key="menu.title"><el-sub-menu :index="menu.title" v-if="menu.children && menu.children.length"><template #title>{{ menu.title }}</template><el-menu-itemv-for="child in menu.children":key="child.path":index="child.path">{{ child.title || child.path }}</el-menu-item></el-sub-menu></div></el-menu></el-aside><!-- 右側主內容區域 --><el-container class="layout-main"><!-- 頂部欄 --><el-header class="layout-header"><div class="header-title">智能控制器后臺系統</div><div class="header-right"><span>管理員</span><el-avatar icon="UserFilled" size="small" /></div></el-header><!-- 面包屑導航 --><el-header class="layout-breadcrumb"><Breadcrumb /></el-header><!-- 頁面主體內容 --><el-main class="layout-content"><router-view /></el-main></el-container></el-container>
</template><script setup>import Breadcrumb from './components/breadcrumb/Breadcrumb.vue';
import {  menus } from '@/config/menu';</script><style scoped>
.layout-container {height: 100vh;
}.layout-aside {background-color: #fff;border-right: 1px solid #e4e7ed;
}.layout-main {flex-direction: column;
}.layout-header {display: flex;justify-content: space-between;align-items: center;background-color: #ffffff;box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);padding: 0 20px;
}.header-title {font-size: 18px;font-weight: bold;
}.layout-breadcrumb {padding: 10px 20px;background-color: #f5f7fa;border-bottom: 1px solid #e4e7ed;
}.layout-content {padding: 20px;background-color: #f9fafb;
}
</style>

Breadcrumb.vue面包屑組件

<template><el-breadcrumb separator="/"><el-breadcrumb-item v-for="item in breadcrumbs" :to="item.path" :key="item.path">{{ item.meta?.title }}</el-breadcrumb-item></el-breadcrumb>
</template><script setup>
import { ref, onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';const route = useRoute();
const breadcrumbs = ref([]);const getBreadcrumbs = () => {const matched = route.matched.filter(item => item.meta?.title);breadcrumbs.value = matched;console.log('breadcrumbs:', breadcrumbs.value);
};// 頁面加載時獲取一次
onMounted(() => {getBreadcrumbs();
});// 監聽路由路徑變化,動態更新面包屑
watch(() => route.path,() => {getBreadcrumbs();}
);
</script>

menus.ts

export const menus = [{title: '用戶管理',children: [{ title: '用戶列表', path: '/user/list' },{ title: '用戶角色管理', path: '/user/role' }]},{title: '權限管理',children: [{ title: '權限列表', path: '/permission/list' }]}]

// src/router/index.ts

// src/router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
// import { CustomRoute } from '@/types/router';
export interface CustomRouteMeta {title: string;
}export type CustomRoute = Omit<RouteRecordRaw, 'meta' | 'children'> & {meta: CustomRouteMeta;children?: CustomRoute[];
};
const routes: CustomRoute[] = [{path: '/',redirect: '/user/list',meta: { title: '首頁' },children: [// 用戶管理 - 父級{path: '/user',redirect: '/user/list',meta: { title: '用戶管理' },children: [{path: 'list',component: () => import('@/pages/user/UserList.vue'),meta: { title: '用戶列表' }},{path: 'details/:id',component: () => import('@/pages/user/UserDetails.vue'),meta: { title: '用戶詳情' }},{path: 'edit/:id',component: () => import('@/pages/user/UserEdit.vue'),meta: { title: '用戶編輯' }},{path: 'settings',component: () => import('@/pages/user/UserSettings.vue'),meta: { title: '用戶設置' }},{path: 'role',component: () => import('@/pages/role/UserRole.vue'),meta: { title: '用戶角色管理' }},{path: 'preferences',redirect: '/user/preferences/settings',meta: { title: '偏好設置' },children: [{path: 'settings',component: () => import('@/pages/user/preferences/PreferenceSettings.vue'),meta: { title: '偏好設置' }},{path: 'edit',component: () => import('@/pages/user/preferences/PreferenceEdit.vue'),meta: { title: '偏好編輯' }}]},{path: 'security',redirect: '/user/security/settings',meta: { title: '安全設置' },children: [{path: 'settings',component: () => import('@/pages/user/security/SecuritySettings.vue'),meta: { title: '安全設置' }},{path: 'modify',component: () => import('@/pages/user/security/SecurityModify.vue'),meta: { title: '安全修改' }}]}]},// 權限管理 - 父級{path: '/permission',redirect: '/permission/list',meta: { title: '權限管理' },children: [{path: 'list',component: () => import('@/pages/permission/PermissionList.vue'),meta: { title: '權限列表' }},{path: 'add',component: () => import('@/pages/permission/PermissionAdd.vue'),meta: { title: '權限添加' }},{path: 'setting',component: () => import('@/pages/permission/PermissionSetting.vue'),meta: { title: '權限設置' }}]}]},{path: '/:pathMatch(.*)*',name: 'NotFound',component: () => import('@/pages/error/404.vue'),meta: { title: '頁面不存在' }}
];const router = createRouter({history: createWebHistory(),routes:routes as unknown as RouteRecordRaw[]
});export default router;

其他文件

│ │ ├── UserList.vue
│ │ ├── UserDetails.vue
│ │ ├── UserEdit.vue
│ │ ├── UserSettings.vue # 用戶設置主頁面
│ │ ├── preferences/
│ │ │ ├── PreferenceSettings.vue # 偏好設置頁面
│ │ │ └── PreferenceEdit.vue # 偏好編輯頁面
│ │ └── security/
│ │ ├── SecuritySettings.vue # 安全設置頁面
│ │ └── SecurityModify.vue # 安全修改頁面

│   │   ├── UserList.vue
<template><div><h2>用戶列表</h2><button @click="goToDetail">查看用戶詳情</button><button @click="goToEdit">編輯用戶信息</button><button @click="goToSettings">用戶設置</button></div>
</template><script setup>
import { useRouter } from 'vue-router';const router = useRouter();
const goToDetail = () => router.push('/user/details/1');
const goToEdit = () => router.push('/user/edit/1');
const goToSettings = () => router.push('/user/settings');
</script>
│   │   ├── UserDetails.vue
<template><h1>用戶詳情</h1>
</template>
│   │   ├── UserEdit.vue
<template><h1>用戶編輯</h1>
</template>
│   │   ├── UserSettings.vue         # 用戶設置主頁面
<template><div><h2>用戶設置</h2><router-link to="/user/preferences/settings"><el-button>進入偏好設置</el-button></router-link><router-link to="/user/security/settings"><el-button>進入安全設置</el-button></router-link><router-view /></div>
</template>
<script setup></script>
│   │   ├── preferences/
│   │   │   ├── PreferenceSettings.vue  # 偏好設置頁面
<template><div><h3>偏好設置</h3><router-link to="/user/preferences/edit"><el-button>編輯偏好設置</el-button></router-link></div>
</template>
│   │   │   └── PreferenceEdit.vue      # 偏好編輯頁面
<template><h1>偏好編輯頁面</h1>
</template>
│   │   └── security/
│   │       ├── SecuritySettings.vue    # 安全設置頁面
<template><h1>安全設置頁面</h1>
</template>
│   │       └── SecurityModify.vue      # 安全修改頁面
<template><h1>安全修改頁面</h1>
</template>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90872.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90872.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90872.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Selenium自動化獲取抖音創作者平臺視頻數據

前言 在當今短視頻盛行的時代&#xff0c;抖音作為國內領先的短視頻平臺&#xff0c;吸引了大量內容創作者。對于創作者而言&#xff0c;了解自己發布的視頻表現&#xff08;如播放量、發布時間等&#xff09;至關重要。本文將介紹如何使用Python的Selenium庫來自動化獲取抖音…

SpringCloud之Eureka

SpringCloud之Eureka 推薦參考&#xff1a;https://www.springcloud.cc/spring-cloud-dalston.html#_service_discovery_eureka_clients 1. 什么是Eureka Eureka 用于簡化分布式系統的服務治理&#xff0c;基于REST的服務&#xff0c;用于服務的注冊與發現。通過注冊發現、客戶…

squash壓縮合并

要將test分支的多次提交合并到dev分支并壓縮為一個commit&#xff0c;核心是使用 git merge --squash 命令&#xff08;壓縮合并&#xff09;&#xff0c;具體步驟如下&#xff1a; 詳細步驟&#xff1a; 1. 切換到dev分支并拉取最新代碼先確保本地dev分支是最新的&#xff0c;…

飛書CEO謝欣:挑戰巨頭,打造AI新時代的Office

引言&#xff1a;飛書要做AI時代辦公協作的逐夢者與破局者。文 | 大力財經在AI浪潮席卷的當下&#xff0c;企業對AI既滿懷期待又充滿焦慮。“AI到底能不能用&#xff1f;AI到底怎么用&#xff1f;”成為縈繞在眾多企業心頭的難題。7月9日召開的飛書未來無限大會&#xff0c;飛書…

React 組件中怎么做事件代理?它的原理是什么?

在 React 組件中&#xff0c;**事件代理&#xff08;Event Delegation&#xff09;**其實是 React 內部實現的一部分&#xff0c;開發者通常無需手動實現事件代理&#xff0c;但理解它的原理和使用方式對于優化性能和掌握底層機制非常重要。一、React 中事件代理的原理React 使…

Vue 2現代模式打包:雙包架構下的性能突圍戰

文章目錄一、場景痛點&#xff1a;兼容性與性能的撕裂二、技術解析&#xff1a;Modern Mode的雙引擎驅動1. 基礎認知&#xff1a;什么是Modern Mode&#xff1f;2. 原理深入&#xff1a;HTML智能分發與Safari 10修復3. 性能收益對比表三、Vue 2項目實戰&#xff1a;啟用Modern模…

UniHttp中HttpApiProcessor生命周期鉤子介紹以及公共參數填充-以百度天氣接口為例

目錄 引言 一、UniHttp與HttpApiProcessor簡介 1、生命周期鉤子的重要性 2、公共參數填充的需求 3、生命周期鉤子相關介紹 二、HttpApiProcessor的實際應用 1、在Yml中定義相關參數 2、自定義HttpAPI注解 3、對接接口的定義 4、HttpApiProcessor的具體實現 5、實際調…

pytorch深度學習—RNN-循環神經網絡

結合生活實例&#xff0c;先簡單認識一下什么是循環神經網絡先想個問題&#xff1a;為什么需要 “循環”&#xff1f;你平時看句子、聽語音、看視頻&#xff0c;都是 “按順序” 來的吧&#xff1f;比如 “我吃蘋果” 和 “蘋果吃我”&#xff0c;字一樣但順序不同&#xff0c;…

深度學習常見名詞解釋、評價指標

目錄 一、魯棒性(robustness) 二、泛化能力&#xff08;Generalization Ability&#xff09; 核心含義&#xff1a; 如何衡量泛化能力&#xff1f; 三、先驗信息&#xff08;Prior Information&#xff09; 四、mIoU &#xff08;Mean Intersection over Union&#xff0…

docker-compose安裝常用中間件

分為3大部分&#xff1a;數據庫&#xff1a;mysql&#xff0c;redis&#xff0c;mongodb&#xff0c;elasticsearch&#xff0c;neo4j&#xff0c;minio&#xff0c;influxdb&#xff0c;canal-server應用中間件&#xff1a;nacos&#xff0c;apollo&#xff0c;zookeeper&…

基于無人機 RTK 和 yolov8 的目標定位算法

目錄 背景 算法思路 代碼實現 驗證 背景 在城市交通巡檢中如何進行車輛違停判斷很重要&#xff0c;一個方法是通過精確坐標判斷車輛中心是否位于違停框中&#xff0c;我們假設無人機坐標已知&#xff0c;并且無人機云臺鏡頭垂直地面朝下&#xff0c;可根據圖像分辨率、無人機參…

go入門 - day1 - 環境搭建

0. 介紹 go語言可以做什么&#xff1f; a. 區塊鏈 b. 分布式/微服務/云原生 c. 服務器/游戲軟件go的優勢 a. 代碼量比C和Java少 b. 編譯速度比Java或者C快上5到6倍&#xff0c;比Scale塊10被 c. 性能比C慢20%&#xff0c;但是比Java、python等快上5到10倍 d. 內存管理和C媲美&a…

【華為OD】MVP爭奪戰(C++、Java、Python)

文章目錄題目描述輸入描述輸出描述示例解題思路算法思路核心步驟代碼實現C實現Java實現Python實現算法要點復雜度分析解題總結題目描述 在星球爭霸籃球賽對抗賽中&#xff0c;最大的宇宙戰隊希望每個人都能拿到MVP&#xff0c;MVP的條件是單場最高分得分獲得者。可以并列所以宇…

Datawhale 2025 AI夏令營 MCP Server Task2

魔搭MCP &Agent賽事&#xff08;MCP Server開發&#xff09;/夏令營&#xff1a;動手開發MCP Server學習鏈接&#xff1a;魔搭MCP &Agent賽事&#xff08;MCP Server開發&#xff09; - Datawhale Task1回顧 1.task1應用功能 luner_info每日黃歷 這是一個可以獲取某天…

敏捷開發方法全景解析

核心理念:敏捷開發是以快速響應變化為核心的項目管理方法論,通過迭代式交付、自組織團隊和持續反饋,實現高質量軟件的高效交付。其本質是擁抱變化優于遵循計劃,強調"可工作的軟件高于詳盡的文檔"。 一、敏捷核心思想體系 #mermaid-svg-y7iyWsQGVWn3IpEi {font-fa…

Socket到底是什么(簡單來說)

簡單來說&#xff1a; Socket 抽象了網絡通信的復雜底層細節&#xff0c;讓應用程序開發者可以專注于發送和接收數據&#xff0c;而不用去操心數據在網絡上是如何傳輸的。 它就像一個“黑盒子”&#xff0c;你只需要把數據扔進去&#xff0c;或者從里面取數據&#xff0c;至于數…

linux系統mysql性能優化

1、系統最大打開文件描述符數查看限制 ulimit -n更改配置 # 第一步 sudo vim /etc/security/limits.conf* soft nofile 1048576 * hard nofile 1048576# 第二步 sudo vim /etc/sysctl.conffs.file-max 1048576# 第三步&#xff08;重啟系統&#xff09; sudo reboot驗證生效 u…

免費的需要嘗試claude code的API安利,截至今天可用(7月13號)

安裝方法放最后&#xff08;很簡單&#xff0c;但是你得搞定網絡&#xff09; 注冊如下&#xff1a; 鏈接如下&#xff08;有詳細說明&#xff09;&#xff1a; &#x1f680; AnyRouter&#xff5c;Claude Code 免費共享平臺 安裝&#xff08;windows用戶特殊點&#xff0…

Java 屬性配置文件讀取方法詳解

Java 屬性配置文件讀取方法詳解 一、配置文件基礎概念 1. 配置文件類型對比類型格式優點缺點適用場景Propertieskeyvalue簡單易讀&#xff0c;Java原生支持不支持層級結構簡單配置&#xff0c;JDBC參數XML標簽層級結構結構化強&#xff0c;支持復雜數據類型冗余&#xff0c;解析…

NW728NW733美光固態閃存NW745NW746

美光NW系列固態閃存深度解析&#xff1a;NW728、NW733、NW745與NW746的全方位評測技術架構與核心創新美光NW系列固態閃存&#xff08;包括NW728、NW733、NW745、NW746&#xff09;的技術根基源于其先進的G9 NAND架構。該架構通過5納米制程工藝和多層3D堆疊技術&#xff0c;在單…