vue实现el-menu与el-tabs联动

news2024/11/17 6:01:32
效果图如下:

在这里插入图片描述

当标签栏很多的时候效果图如下:

在这里插入图片描述

左侧菜单布局 ($route.path高亮显示激活路由 :default-active="$route.path"

 <el-menu
          :default-active="$route.path"
          class="el-menu-vertical-demo"
          background-color="#323744"
          text-color="#fff"
          active-text-color="#409eff"
          :collapse="iscollapse"
          unique-opened
          :collapse-transition="false"
          router
        >
         
          <template v-for="(item, index) in menuList">
             <!-- 有下拉 -->
            <el-submenu v-if="item.children" :index="item.id" :key="index">
              <template slot="title">
                <svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
                <span>{{ item.title }}</span>
              </template>
              <el-menu-item-group
                v-for="(item, index) in item.children"
                :key="index"
              >
                <el-menu-item :index="item.path" @click="clickMenu(item)">
                  <template slot="title">
                    <svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
                    <span>{{ item.subtitle1 }}</span>
                  </template>
                </el-menu-item>
              </el-menu-item-group>
            </el-submenu>

            <!-- 没有下拉 -->
            <el-menu-item v-else :key="index" :index="item.path" @click="clickMenu(item)">
              <svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
              <span slot="title">{{ item.subtitle1 }}</span>
            </el-menu-item>
          </template>
        </el-menu>
模拟数据如下:(以下路径均需在router/index.js里面进行配置)
menuList: [
        {
          id: "9",
          subtitle1: "首页",
          icon: "shangjiadianpu",
          path: "/welcome",
        },
        {
          id: "1",
          title: "用户管理",
          icon: "huangguanyonghu",
          children: [
            {
              id: "1-1",
              subtitle1: "时间-moment",
              icon: "huangguanyonghu",
              path: "/user",
            },
            {
              id: "1-2",
              subtitle1: "删除用户",
              icon: "huangguanyonghu",
              img: require("@/assets/logo.png"),
              path: "/user2",
            },
            {
              id: "1-3",
              subtitle1: "图片放大",
              icon: "huangguanyonghu",
              path: "/user3",
            },
          ],
        },
        {
          id: "2",
          title: "表格",
          icon: "ershoujiaoyi",
          children: [
            {
              id: "2-1",
              subtitle1: "表格排序",
              icon: "ershoujiaoyi",
              path: "/tableSort",
            },
            {
              id: "2-2",
              subtitle1: "动画",
              icon: "ershoujiaoyi",
              path: "/animation",
            },
            {
              id: "2-3",
              subtitle1: "权限3",
              icon: "ershoujiaoyi",
              path: "/limit3",
            },
          ],
        },
        {
          id: "6",
          subtitle1: "拖拽-sortablejs",
          icon: "shangpuchuzu",
          path: "/sortable",
        },
         {
          id: "7",
          title: "功能",
          icon: "ershoujiaoyi",
          children: [
            {
              id: "7-1",
              subtitle1: "上下滚动",
              icon: "ershoujiaoyi",
              path: "/numscroll",
            },
             {
              id: "7-9",
              subtitle1: "数字滚动",
              icon: "ershoujiaoyi",
              path: "/icountup",
            },
            {
              id: "7-2",
              subtitle1: "动画",
              icon: "ershoujiaoyi",
              path: "/animation",
            },
            {
              id: "7-3",
              subtitle1: "调用摄像头",
              icon: "ershoujiaoyi",
              path: "/opencamera",
            },
            {
              id: "7-4",
              subtitle1: "裁剪图片",
              icon: "ershoujiaoyi",
              path: "/cropperjs",
            },
            {
              id: "7-5",
              subtitle1: "裁剪图片2",
              icon: "ershoujiaoyi",
              path: "/vuecropper",
            },
            {
              id: "7-6",
              subtitle1: "打印功能",
              icon: "ershoujiaoyi",
              path: "/printjs",
            },
            {
              id: "7-7",
              subtitle1: "vue-pfd预览",
              icon: "ershoujiaoyi",
              path: "/vuepdf",
            },
             {
              id: "7-8",
              subtitle1: "内嵌iframe",
              icon: "ershoujiaoyi",
              path: "/iframepdf",
            },
             {
              id: "7-10",
              subtitle1: "放大镜功能",
              icon: "ershoujiaoyi",
              path: "/magnifier",
            },
            {
              id: "7-11",
              subtitle1: "多表头表格",
              icon: "ershoujiaoyi",
              path: "/xlsx",
            },
            {
              id: "7-12",
              subtitle1: "单表头表格",
              icon: "ershoujiaoyi",
              path: "/xlsx2",
            },
             {
              id: "7-13",
              subtitle1: "Vuecontextmenu",
              icon: "ershoujiaoyi",
              path: "/vuecontextmenu",
            },
            {
              id: "7-14",
              subtitle1: "vcontextmenu",
              icon: "ershoujiaoyi",
              path: "/vcontextmenu",
            },
            {
              id: "7-15",
              subtitle1: "表格合并",
              icon: "ershoujiaoyi",
              path: "/tablehebing",
            },
            {
              id: "7-16",
              subtitle1: "日期选择",
              icon: "ershoujiaoyi",
              path: "/datepicker",
            },
            {
              id: "7-17",
              subtitle1: "treeselect",
              icon: "ershoujiaoyi",
              path: "/treeselect",
            },
            {
              id: "7-19",
              subtitle1: "大屏数据",
              icon: "ershoujiaoyi",
              path: "/datav",
            },
            {
              id: "7-20",
              subtitle1: "左右菜单联动",
              icon: "ershoujiaoyi",
              path:'/leftrightmenu'
            },
            {
              id: "7-18",
              subtitle1: "测试页面",
              icon: "ershoujiaoyi",
              path: "/test",
            },
          ],
        },
      ],

主要内容区域标签栏布局如下:

	<el-tabs
	  class="vab-tabs-content"
	    v-model="activeIndex"
	    type="card"
	    @tab-click="clickTab"
	    @tab-remove="removeTab"
	    
	  >
	      <el-tab-pane
	        v-for="item of openTab"
	        v-if="openTab.length"
	        :key="item.name"
	        :label="item.name"
	        :name="item.route"
	        :closable="isNoClosable(item)"
	      >
	      </el-tab-pane>
  </el-tabs>
标签栏样式
/deep/.el-tabs__header .el-tabs__nav{
    border:none;
  }
  /deep/.el-tabs--card>.el-tabs__header{
    border:none;
  }
  /deep/.el-tabs__header .el-tabs__item{
    padding:0 30px;
    border:none
  }
  /deep/.el-tabs__header .el-tabs__item.is-active {
    color: #1890ff;
    background: #e8f4ff;
    outline: none;
    -webkit-mask: url(~@/assets/images/tabs-bg.png);
    mask: url(~@/assets/images/tabs-bg.png);
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
}
  /deep/.el-tabs__header .el-tabs__item:hover {
      color: #515a6e;
      background: #dee1e6;
      -webkit-mask: url(~@/assets/images/tabs-bg.png);
      mask: url(~@/assets/images/tabs-bg.png);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
  }
  /deep/.el-tabs--card > .el-tabs__header .el-tabs__item.is-closable:hover {
      padding-left: 30px;
      padding-right: 30px;
  }
  /deep/.el-tabs__header .el-tabs__item.is-active.is-closable {
    padding-left: 30px;
    padding-right: 30px;
}
  /deep/.el-tabs__header .el-tabs__item.is-active:hover {
      color: #1890ff !important;
      background: #e8f4ff !important;
      // padding: 0 30px 0 30px;
  }
  .el-tabs__header .el-tabs__item.is-active:hover {
    color: #1890ff;
    background: #e8f4ff;
    -webkit-mask: url(~@/assets/images/tabs-bg.png);
    mask: url(~@/assets/images/tabs-bg.png);
    -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
  }

创建一个仓库模块 @/store/Modules/tabs.js

在这里插入图片描述

tabs.js代码如下

export default{
    namespaced: true,  //开启命名空间
    state: {
        openTab: JSON.parse(sessionStorage.getItem('openTab'))|| [],
        activeIndex: ''
      },
      mutations: {
        add_tabs (state, data) {
          //如果等于-1说明tabs不存在那么插入,否则什么都不做
          //findindex找角标,循环判断一下,如果等于那么就代表有相同的,就不必添加,如果找不到那就是-1.就添加
          let result = state.openTab.findIndex(item => item.name === data.name);
          result === -1 ? state.openTab.push(data) : '';
          // 存到本地 页面刷新不丢失
          sessionStorage.setItem('openTab',JSON.stringify(state.openTab))
        },
        delete_tabs (state, route) {
          let index = 0
          for (let gohh of state.openTab) {
            if (gohh.route === route) {
              break
            }
            index++
          }
          state.openTab.splice(index, 1)
          // 存到本地 页面刷新不丢失
          sessionStorage.setItem('openTab',JSON.stringify(state.openTab))
        },
        set_active_index (state, index) {
            console.log(index);
          state.activeIndex = index
        }
      }
}
将tab.js模块引入@store/index.js

import Vue from 'vue'
import Vuex from 'vuex
import tabs from './Modules/tabs'
Vue.use(Vuex)
export default new Vuex.Store({
  state: { 
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    tabs
  }
})
主要逻辑代码如下:
在主要内容区域引入如下代码获取tabs.js仓库里面的值在页面进行渲染
  computed: {
    openTab () {
      return this.$store.state.tabs.openTab
    },
    activeIndex: {
      get () {
        return this.$store.state.tabs.activeIndex
      },
      set (val) {
        this.$store.commit('tabs/set_active_index', val)
      }
    }
  },
左侧菜单导航绑定点击事件clickMenu,去触发仓库的add_tabs事件,把数组添加到openTab数组里面(添加前需要判断openTab是否有当前值,有就不添加,反之添加),把activeIndex也改变
clickMenu(val){
   //备注 :分模块触发事件可参考vue官网  '模块名/事件名'
    this.$store.commit('tabs/add_tabs',{route: val.path , name: val.subtitle1 })
    this.$store.commit('tabs/set_active_index', val.path)
 },
标签绑定点击事件clickTab 跳转到对应路由,给标签叉叉绑定removeTab (tab-remove 点击 tab 移除按钮后触发 被删除的标签的 name)拿到对应的路由进行判断

1、如果是首页则不删除;
2、如果删除的高亮激活这一项,则跳转到最后openTab数组的最后一项并高亮;
3、如果删除的不是高亮激活这一项,则不跳转,高亮激活项不变。

clickTab (tab) {
   console.log(tab);
   this.$router.push({path: this.activeIndex})
 },
 removeTab (target) {
   if(target == '/'||target == '/welcome'){
      return
    }
   this.$store.commit('tabs/delete_tabs', target)
   if (this.activeIndex === target) {
     // 设置当前激活的路由
     if (this.openTab && this.openTab.length >= 1) {
       console.log('=============', this.openTab[this.openTab.length - 1].route)
       this.$store.commit('tabs/set_active_index', this.openTab[this.openTab.length - 1].route)
       this.$router.push({path: this.activeIndex})
     }
   }
 },
el-tab-pane标签绑定属性 :closable="isNoClosable(item)判断el-tab-pane是否显示叉叉,除了首页不显示,其他均显示
isNoClosable(item){
   return item.route !== '/welcome'
 },
刷新时以当前路由做为tab加入tabs,当前路由不是首页时,添加首页以及另一页到store里,并设置激活状态,当前路由是首页时,添加首页到store,并设置激活状态(注意:this.$route.meta.title的title值要和菜单数据里面的subtitle1名称保持一致!!!)

在这里插入图片描述

mounted () {
    console.log(this.$route);
    // 刷新时以当前路由做为tab加入tabs
    // 当前路由不是首页时,添加首页以及另一页面到store里,并设置激活状态
    // 当前路由是首页时,添加首页到store,并设置激活状态
    if (this.$route.path !== '/welcome') {
      this.$store.commit('tabs/add_tabs', {route: '/welcome' , name: '首页'})
      this.$store.commit('tabs/add_tabs', {route: this.$route.path , name: this.$route.meta.title })
      this.$store.commit('tabs/set_active_index', this.$route.path)
      
    } else {
      this.$store.commit('tabs/add_tabs', {route: '/welcome', name: '首页'})
      this.$store.commit('tabs/set_active_index', '/welcome')
      
    }
  }

实现思路大致就是这样,主要自己项目的数据稍作修改。

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

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

相关文章

通达信吊灯止损指标公式,根据波动幅度自动调整止盈止损

吊灯止损指标是由查克勒博(Chuck LeBeau)发明的&#xff0c;亚历山大埃尔德(Alexander Elder)在其著作《走进我的交易室》中介绍了这种止盈止损方法&#xff08;中文版翻译为倒挂式离场法则&#xff09;&#xff0c;它是根据平均真实波幅ATR设置跟踪止损。吊灯止损指标的目的是…

【Java系列】SpringBoot 集成MongoDB 详细介绍

目录 写在前面 一、步骤介绍 步骤 1: 添加 MongoDB 依赖 步骤 2: 配置 MongoDB 连接信息 步骤 3: 创建实体类 步骤 4: 创建 Repository 接口 步骤 5: 使用 Repository 进行操作 二、特殊处理 写在前面 在Spring Boot中集成MongoDB的过程相对简单&#xff0c;以下是一个…

基于单片机公交安全预警系统仿真设计

**单片机设计介绍&#xff0c; 基于单片机公交安全预警系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的公交安全预警系统可以被设计成能够实时监测公交车辆的行驶状态&#xff0c;并在发生异常情况时进行…

【Computer Vision Foundation】全球计算机视觉基金会论文网

计算机视觉基金会&#xff08;Computer Vision Foundation&#xff0c;简称CVF&#xff09;是一个致力于推动计算机视觉领域研究和发展的组织。以下是关于计算机视觉基金会的一些基本信息&#xff1a; 成立目的&#xff1a; CVF成立的目的是促进计算机视觉领域的学术研究、技术…

【微服务】SaaS云智慧工地管理平台源码

智慧工地系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段&#xff0c;实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 一、智慧工地让工程施工智能化 1、内容全面&#xff0c;多维度数…

【运维】永久关闭selinux不当,导致无法启动

现象: 卡centos loading进度条 按esc键发现,启动报错: Failed to load SElinux policy ,freezing 可能的原因: selinuxdisabled 写错成disable 或者 错误的把selinuxtype改了&#xff0c;要改文中红框的部分。 解决方案: 1. 重启 2. 出现选择画面的时候 按e 3. 方向下键…

Shell判断:模式匹配:case(二)

简单的JumpServer 1、需求&#xff1a;工作中&#xff0c;我们需要管理N多个服务器。那么访问服务器就是一件繁琐的事情。通过shell编程&#xff0c;编写跳板程序。当我们需要访问服务器时&#xff0c;看一眼服务器列表名&#xff0c;按一下数字&#xff0c;就登录成功了。 2、…

【Vue】响应式与数据劫持

目录 前言 响应式 Vue的响应式是如何实现的 数据劫持 Vue中的data属性都具有响应式 Vue后期添加的属性如何使其具有响应式 数组的响应式处理 如何使用数组下标去修改可以具有响应式呢 前言 什么是响应式&#xff1f;数据劫持是什么&#xff1f;Vue响应式是如何实现的&a…

VScode调试没有反应

点击调试按钮后没反应 有可能是vscode中安装的python插件版本问题 可以通过重新安装比较旧一点的python尝试解决此问题 步骤如下&#xff1a; 然后从中选择比当前版本更低的版本即可 安装完成后需重启vscode

Unity中Shader的PBR的基础知识与理论

文章目录 前言一、什么是PBR二、什么是PBS在这里插入图片描述 三、PBS的核心理论1、物质的光学特性&#xff08;Substance Optical Properties&#xff09;2、微平面理论&#xff08;Microfacet Theory&#xff09;3、能量守恒&#xff08;Energy Conservation&#xff09;4、菲…

Linux中的MFS分布式文件系统

目录 一、MFS分布式文件系统 1、MooseFS简介 2、Moose File System的体系结构 &#xff08;1&#xff09;MooseFS Master &#xff08;2&#xff09;MooseFS Chunk Server &#xff08;3&#xff09;MooseFS Metalogger &#xff08;4&#xff09;MooseFS Client &…

InnoDB 的一次更新事务是怎么实现的?

大体流程&#xff1a; 步骤: 1.加载数据到缓存中&#xff08;Buffer Pool&#xff09;&#xff1a; 在进行数据更新时&#xff0c;InnoDB首先会在缓冲池&#xff08;Buffer Pool&#xff09;中查找该记录是否已经在内存中。如果记录不在内存中&#xff0c;会将需要更新的数据…

django+drf+vue 简单系统搭建 (3) - 基于类的视图

传统Django中有基于类的视图&#xff0c;Drf中自然也有&#xff0c;目的都是实现功能的模块化继承&#xff0c;封装&#xff0c;减少重复代码。 首先在视图中新增下面代码&#xff1a; # simpletool/views.pyfrom rest_framework.views import APIView from simpletool.seria…

matplotlib violinplot换颜色

本来用的是箱图&#xff0c;后来发现这个图更好看&#xff0c;就想要学习一下&#xff0c;官方有给教程&#xff0c;当然可以直接学习 https://matplotlib.org/stable/gallery/statistics/customized_violin.html 以上是官方给的&#xff0c;效果是这个样子的 这个从最基本的蓝…

redis运维(十二)

一 位图 ① 概念 1、说明&#xff1a;位图还是在操作字符串2、位图玩字符串在内存中存储的二进制3、ASCII字符通过映射转化为二进制4、操作的是字符串value ② ASCII字符铺垫 1、控制ASCII字符 2、ASCII可显示字符 ③ SETBIT 细节&#xff1a; setbit 命令的返回值是之…

stack和queue简单实现(容器适配器)

容器适配器 stack介绍stack模拟实现queue 介绍queue模拟实现deque stack介绍 stack模拟实现 以前我们实现stack&#xff0c;需要像list,vector一样手动创建成员函数&#xff0c;成员变量。但是stack作为容器适配器&#xff0c;我们有更简单的方法来实现它。 可以利用模板的强大…

linux之chmod命令

在linux系统中经常遇到需要对文件修改读写执行的权限&#xff0c;下面对chomod命令进行梳理总结。 1、文件权限 在linux系统中&#xff0c;每个文件都有归属的所有者和所有组&#xff0c;并且规定了文件的所有者、以及其他人对文件所拥有的可读&#xff08;r&#xff09;、可写…

年薪30w项目经理都在用的6个项目管理软件

大家好&#xff0c;我是老原。又到了每月一次的好用工具推荐&#xff0c;不少粉丝都在搓手等待了。 要知道&#xff0c;实时掌握项目进度、把关项目质量、应对项目风险、协调资源…如果能好用的工具高效提升你的工作效率&#xff0c;对于领导来说&#xff0c;绝对是加分项。 …

linux:查看文件前100行和后100行

查看文件中的前100行 head -n 100 文件名查看文件中的后100行 tail -n 100 文件名

《洛谷深入浅出基础篇》P3916 图的遍历——逆向搜索

上链接&#xff1a; P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3916上题干&#xff1a; 题目描述 给出 N 个点&#xff0c;M 条边的有向图&#xff0c;对于每个点 v&#xff0c;求 A(v) 表示从点 v 出发&#xff0c;能到…