[VUE学习]权限管理系统前端vue实现9-动态路由,动态标签页,动态面包屑

news2024/11/15 8:27:41

1.动态路由

        1.因为我们左侧权限菜单是根据不同用户显示不一样的 所以我们需要使用动态路由 来动态生成右侧路由信息

                在总体布局页面添加router

  • <router-view> 是 Vue Router 提供的组件,用于动态展示匹配到的路由组件内容。
  • 通过在合适的位置放置 <router-view>,你可以根据路由路径动态地渲染对应的组件内容。

         2.router里面需要添加children 

                    因为我们是多级页面 之后动态路由也是多级的 如果这里不提前写children 之后动态生成的时候找不到Children

         3.做动态路由是否生成判断 尽量减少生成次数

          1.在store里面添加全局状态

        4.permission.js

router.beforeEach((to,from,next)=>{
    const whiteList=['/login'] // 白名单
    let token=store.getters.GET_TOKEN;
    let hasRoutes = store.state.hasRoutes;
    let menuList = store.getters.GET_MENULIST
    if(token){
        if(!hasRoutes){
            bindRoute(menuList);
            store.commit("SER_ROUTES_STATE",true)
//注意这一行代码 在这一篇文章 详细解释了 如不过写会刷新白屏
            next({ ...to, replace: true })
        }else{
            next();
        }

    }else{
        if(whiteList.includes(to.path)){
            next();
        }else{
            next("/login");
        }
    }
})
const bindRoute=(menuList)=>{
    let newRoutes = router.options.routes;
    menuList.forEach(menu=>{
        if(menu.children){
            menu.children.forEach(m=>{
                let route = menuToRoute(m,menu.name)
                if(route){
                    newRoutes[0].children.push(route);
                }
            })
        }
    })
    //重新添加到路由
    newRoutes.forEach(route=>{
        router.addRoute(route)
    })
}
const menuToRoute=(menu,parentName)=>{
    if(!menu.component){
        return null;
    }else{
        let route={
            name:menu.name,
            path:menu.path,
            meta:{
                parentName:parentName
            }
        }
        route.component=()=>import('@/views/'+menu.component+'.vue')
        return route
    }
}

        1.menuList是我们在登录时候得到的 树形结构 表结构

         2.menuToRounte是动态生成路由  我们传入menu和父级名字(因为父级名字之后会用到)

             生成route对象 包括 name  path  和父级名字 

             component对应着目录结构

          3.生成之后 然后把他们添加到路由里面

       

  1. bindRoute 函数用于将菜单列表转换为路由配置,并添加到路由实例中。它遍历菜单列表,并根据每个菜单项生成对应的路由配置,然后将这些路由配置添加到 newRoutes 数组中。最后,通过 router.addRoute 方法将所有路由配置添加到路由实例中。

  2. menuToRoute 函数用于将菜单项转换为路由配置。如果菜单项没有指定组件,则返回 null;否则,生成一个包含菜单名、路径和父菜单名的路由配置对象,并设置组件为异步加载形式。

2.动态标签页

        

 1.store里面添加标签页数组 一个是当前标签页 一个是全部打开的

         

    state: {
        hasRoutes: false,
        editableTabsValue: '/index',
        editableTabs: [
            {
                title: '首页',
                name: '/index'
            }
        ]
    },

       

        ADD_TABS: (state, tab) => {
            if (state.editableTabs.findIndex(e => e.name == tab.path) === -1) {
                state.editableTabs.push({
                    title: tab.name,
                    name: tab.path
                })
            }
            state.editableTabsValue = tab.path
        },
        RESET_TABS: (state) => {
            state.editableTabsValue = '/index',
                state.editableTabs = [
                    {
                        title: '首页',
                        name: '/index'
                    }
                ]
        },

安全退出时候 调用RESET_TABS这个方法 清空

  if(result.data.code===200){
    store.commit("SER_ROUTES_STATE",false)
    store.commit("RESET_TABS")
    store.dispatch('logout')
  }

在menuIndex里面添加 click点击事件

2.tabIndex具体实现

        1.关联store里面数据

                涉及到路由 使用useRouter

const router = useRouter();
const editableTabsValue = ref(store.state.editableTabsValue)
const editableTabs = ref(store.state.editableTabs)

                 因为我们关联的是store里面的数据 所以当我们store里面数据发生更改之后 页面并没有发生改变 所以我们需要对数据进行监听 当发生更改之后 重新赋值

<template>

<!--  选中-->
  <el-tabs
      v-model="editableTabsValue"
      type="card"
      class="demo-tabs"
      closable
      @tab-remove="removeTab"
      @tab-click="clickTab"
  >
<!-- 所有tab-->
    <el-tab-pane
        v-for="item in editableTabs"
        :key="item.name"
        :label="item.title"
        :name="item.name"
    >
      {{ item.content }}
    </el-tab-pane>
  </el-tabs>
</template>
<script  setup>
import {ref, watch} from 'vue'
import store from '@/store'
import {useRouter} from "vue-router";

const router = useRouter();

const editableTabsValue = ref(store.state.editableTabsValue)
const editableTabs = ref(store.state.editableTabs)


const removeTab = (targetName) => {
  const tabs = editableTabs.value
  let activeName = editableTabsValue.value

  // 这里是Path  使得无法删除首页
  if(targetName==='/index'){
    return
  }

  if (activeName === targetName) {
    tabs.forEach((tab, index) => {
      if (tab.name === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1]
        if (nextTab) {
          activeName = nextTab.name
        }
      }
    })
  }

  editableTabsValue.value = activeName
  editableTabs.value = tabs.filter((tab) => tab.name !== targetName)

  store.state.editableTabsValue = editableTabsValue.value
  store.state.editableTabs=editableTabs.value

  // 这个获取的是path
  router.push({path:activeName})
}

const refreshTabs =()=>{
  editableTabsValue.value=store.state.editableTabsValue;
  editableTabs.value=store.state.editableTabs;
}

// 可以拿到标签名称 可以根据Name  也可以根据path
const clickTab =(target)=>{
  router.push({name:target.props.label})
}

// 监听变化
watch(store.state,()=>{
  refreshTabs();
},{deep:true,immediate:true})
// 深度监听

</script>
<style>
.demo-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}

.el-main{
  padding:0px;
}


.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{
  background-color: lightgray;
}

.el-tabs{
  height:45px
}
</style>

3.动态面包屑实现

        面包屑

         这里就使用到了我们前面提到的parentName 

        三个if  

        如果是父级名字 并且index大于一 显示并且加 /  系统管理/

        如果是最后一个直接显示      角色管理

<template>
  <el-icon><HomeFilled /></el-icon>
    <el-breadcrumb separator="/">

      <el-breadcrumb-item v-for="(item,index) in breadcrumbList" :key="index">
        <span class="root" v-if="parentName && index>0">{{parentName}}&nbsp;&nbsp;/&nbsp;&nbsp;</span>
        <span class="leaf" v-if="index==breadcrumbList.length-1">{{item.name}}</span>
        <span class="root" v-else>{{item.name}}</span>
      </el-breadcrumb-item>

    </el-breadcrumb>
</template>

<script setup>
import { ref,watch } from 'vue'
import {HomeFilled} from '@element-plus/icons-vue'
import {useRoute} from 'vue-router'
import store from "@/store";

const route=useRoute();
const breadcrumbList=ref([]);
const parentName=ref("")

const initBreadcrumbList=()=>{
  breadcrumbList.value=route.matched;
  parentName.value=route.meta.parentName;
}

watch(route,()=>{
  initBreadcrumbList();
},{deep:true,immediate:true})


</script>

<style lang="scss" scoped>
.leaf{
  cursor:text;
}
.root{
  color:#666;
  font-weight:600;
}
</style>

4.路由与导航动态绑定实现

             为了防止有人不点击 直接输入Url跳转  首先App.vue里面监听 然后添加标签页数据  此时标签页可以动态变化

import { ref ,watch} from 'vue'
import { useRoute,useRouter } from 'vue-router'
const route=useRoute();
const router=useRouter();
const whitePath=['/login','/index','/']


watch(route,(to,from)=>{
  console.log("to"+to.name)
  console.log(to.path)

  if (whitePath.indexOf(to.path)===-1) {
    console.log("to.path="+to.path)
    let obj = {
      name: to.name,
      path: to.path
    }

    store.commit("ADD_TABS", obj)
  }

},{deep:true,immediate:true})

        修改menu使得菜单栏也可以动态变化

 

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

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

相关文章

将word中超链接的字体颜色更换成白色

文章目录 1、问题描述2、解决方法&#xff08;两种&#xff09;2.1 临时修改2.2 永久修改 1、问题描述 超链接是蓝色&#xff0c;需要将其换成正常颜色的字体 2、解决方法&#xff08;两种&#xff09; 2.1 临时修改 直接选中该字体&#xff0c;从字体的颜色那里选主题颜色…

zabbix安装监控客户端应用

添加 zabbix 客户端主机 服务端和客户端都配置时间同步 服务端和客户端都设置 hosts 解析 设置 zabbix 的下载源&#xff0c;安装 zabbix-agent2 在服务端验证 zabbix-agent2 的连通性 ​编辑 在 Web 页面中添加 agent 主机 自定义监控内容 在客户端创建自定义 key 1.明确…

XSS学习

目录 什么是XSS 概念 理解 XSS分类 存储型XSS 反射型XSS 原理 攻击过程 DOM型 攻击过程 DOM行XSS与反射型XSS区别 存储型XSS与反射型XSS区别 DVWA实验 反射型XSS low等级 JavaScript弹窗函数 攻击思路 攻击者web设计 medium等级 high等级 impissible等级 …

【ES6】中构造函数的语法糖 —— Class(类)

在现代前端开发中&#xff0c;JavaScript的面向对象编程成为了主流。ES6引入了class关键字&#xff0c;使得开发者可以更方便地使用面向对象的方式编写代码&#xff0c;更接近传统语言的写法。ES6的class可以看作是一个语法糖&#xff0c;它的绝大部分功能ES5都可以做到&#x…

Java基础---动态代理

目录 典型回答 静态代理和动态代理的区别 动态代理的用途 Spring AOP的实现方式 JDK 动态代理的代码段 Cglib动态代理的代码段 典型回答 动态代理就是&#xff0c;在程序运行期&#xff0c;创建目标对象的代理对象&#xff0c;并对目标对象中的方法进行功能性增强的一种技…

electron+vue3全家桶+vite项目搭建【22】vite定义编译时全局变量,用于渲染进程判断当前是否为打包环境

引入 demo项目地址 我们在本地运行时往往显示的是一些方便调试的页面&#xff0c;如下所示: 通过页面路由选择&#xff0c;快速打开不同的窗口 而当我们打包运行时&#xff0c;往往希望直接进入软件的主页&#xff0c;而不显示这些调试页面&#xff0c;也许你会觉得&#xf…

设计模式之三:装饰者模式

装饰者模式可以在不修改任何底层代码的情况下&#xff0c;给对象赋予新的职责&#xff08;使用对象组合的方式&#xff0c;在运行时装饰类&#xff09;。 假定星巴兹咖啡需要更新订单系统&#xff0c;而他们原先类的设计如图&#xff1a; 现在他们考虑客户可以选择添加调料&am…

day62_ssm事务

今日内容 零、 复习昨日 零、 复习昨日 excel导入导出,cv配置和方法 aop: 面向切面编程 抽取与业务无关的代码,比如日志记录,事务控制,权限校验等,形成一个切面 利用动态代理的技术将切面中的增强方法,作用到目标方法上 aop日志 日志注解切面类 切入注解获得时间,ip,session中的…

跟我一起从零开始学python(四)数据库编程:MySQL数据库

前言 回顾之前讲了python语法编程 &#xff0c;必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;今天到了数据库编程篇&#xff0c;前面没看的也不用往前翻&#xff0c;系列文已经整理好了&#xff1a; 1.跟我一起从零开始学python&#xff08…

探索MySQL的秘密宝藏:寻找隐藏的金币数据!(面试)

目录 ✨前言 &#x1f6b6;‍♂️正片开始 一、常见MySQL面试题通关详解 二、SQL面试题实战 1. 某外卖公司的用户订单表面试题 2. 学生管理系统表面试题 &#x1f44b;尾记 前言 在一个神秘的岛屿上&#xff0c;有一个被称为"数据库之塔"的巨大建筑。据传说&a…

Kubernetes Pod卷 - Pod镜像的升级和回滚 - 探针

目录 扩展&#xff1a; Pod创建的拓扑图&#xff1a; 提出的问题&#xff1a; Pod 卷的使用&#xff1a;Pod的数据持久化问题 配置 Pod 以使用卷进行存储 参考文档&#xff1a;配置 Pod 以使用卷进行存储 | Kubernetes 有状态应用和无状态应用&#xff1a; Pod 配置卷 1…

122.将实战网页部署到Netlify

● 本章我们将网站部署到Netlify ● 首先先点击右上角注册一个账号 ● 注册完成之后&#xff0c;点击sites&#xff0c;将我们的网站文件夹拖入 ● 上传成功 ● 之后就可以正常访问啦 ● 我们也可以修改我们的站点名称&#xff0c;让他更加好记

1、简述MySQL体系结构。2、安装部署MySQL。(使用yum以及通用二进制方式)。

Mysql是由SQL接口&#xff0c;解析器&#xff0c;优化器&#xff0c;缓存&#xff0c;存储引擎组成的 Connectors指的是不同语言中与SQL的交互 Management Serveices & Utilities&#xff1a; 系统管理和控制工具 Connection Pool&#xff1a;连接池。管理缓冲用户连…

JAVA_WEB 学生信息管理系统(WEB端)

仓库地址&#xff1a;https://gitee.com/ThMyGitee/Stuednt.git CSDN的友友们&#xff0c;项目如果适合您的话&#xff0c;麻烦给个小小的Star&#xff0c;谢谢啦&#xff01; JAVA_WEB 学生信息管理系统(WEB端) 1.开发环境 JDK1.8 Tomcat 8.5.60 IDEA 2019.3 MySQL 5.7.20…

算法学习day22

235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&…

洞察顾客需求,探究问卷调查在餐饮行业的赋能之路!

在餐饮行业中&#xff0c;顾客的口碑占据非常重要的地位&#xff0c;直接影响着门店的销售额。好口碑能一传十、十传百&#xff0c;为门店带来持续不断的流量和收益。所以&#xff0c;在顾客体验这一块&#xff0c;餐饮门店要尤为重视。 某餐饮品牌作为全球知名品牌&#xff0c…

精选6种制作竞赛动图的方法,推荐收藏!

下面的两个动图&#xff0c;就是条形竞赛图和折线竞赛图。 今天我们就来看看都有哪些方便的方法来制作呢 技术交流 技术要学会分享、交流&#xff0c;不建议闭门造车。一个人可以走的很快、一堆人可以走的更远。 本文文章由粉丝的分享、推荐&#xff0c;资料干货、资料分享、…

牛客小白月赛75 DE

D 矩阵 登录—专业IT笔试面试备考平台_牛客网 思路&#xff1a;我们能够发现每个点最多只用两种状态&#xff0c;一种是不变&#xff0c;另一种是改变&#xff0c;如果相邻的点与当前点不相同&#xff0c;则可以花费一个单位走过去&#xff0c;否则需要先改变它的状态&#x…

7.4 实战图书详情相关接口(管理员端)

文章目录 前言一、需求二、Service层2.1 图书详情 - 基本信息接口BookDetailBOBookServiceBookServiceImpl 2.2 图书详情 - 图书评论接口BookCommentBOStudentBOBookCommentServiceBookCommentServiceImpl 三、Web层BookAdminController 四、PostMan测试最后 前言 在前面的API…

深入理解Linux内核网络——内核与用户进程协作之同步阻塞方案(BIO)

文章目录 一、相关实际问题二、socket的直接创建三、内核和用户进程协作之阻塞方式1&#xff09;等待接收消息2&#xff09;软中断模块3&#xff09;同步队列阻塞总结 在上一部分中讲述了网络包是如何从网卡送到协议栈的&#xff08;详见深入理解Linux网络——内核是如何接收到…