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

效果图如下:

在这里插入图片描述

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

在这里插入图片描述

左侧菜单布局 ($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')
      
    }
  }

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Hello Go】Go语言文本文件处理

文本文件处理 字符串处理字符串操作ContainsJoinindexrepeatReplaceSplitTrimFields 字符串转换AppendFormatParse 正则表达式Json处理编码Json通过结构体生产Json通过map生产json 解码Json解析到结构体解析到interface 文件操作相关api介绍建立和打开文件关闭文件写文件读文件…

深度学习卫星遥感图像检测与识别 -opencv python 目标检测 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐…

优秀智慧园区案例 - 三亚市崖州湾科技城智慧园区,先进智慧园区建设方案经验

一、项目背景 三亚崖州湾科技城作为海南自贸港建设的重点园区&#xff0c;是重点推进的海南自贸港先导项目之一。崖州湾科技城全力抢抓有利时机&#xff0c;进一步拓宽发展思路&#xff0c;持续深化体制机制创新&#xff0c;牢牢把握“打造产学研城深度融合的聚集地”这一核心…

nodejs express vue uniapp新闻发布系统源码

开发技术&#xff1a; node.js&#xff0c;mysql5.7&#xff0c;vscode&#xff0c;HBuilder nodejs express vue uniapp 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索新闻&#xff0c;新闻分类&#xff0c;新闻列表 点击新闻进入新闻详情&#xff0…

代码随想录第六十三天 | 单调栈:寻找 左边 / 右边 距离当前元素最近的 更小 元素的 下标(暴力,双指针,单调栈)(84);代码随想录主要题目结束

1、寻找 左边 / 右边 距离当前元素最近的 更小 元素的 下标 1.1 leetcode 84&#xff1a;柱状图中最大的矩形 第一遍代码思路错了&#xff0c;如&#xff1a;输入[2,1,2]&#xff0c;对于2&#xff0c;因为比栈顶元素1大&#xff0c;然后就会直接得出2&#xff08;1&#xff…

vite构建项目不能使用require解决方案

在utils文件夹下创建一个getImgUrl.ts文件 /** vite的特殊性, 需要处理图片 */ export const require (imgPath: string) > {try {const handlePath imgPath.replace(, ..)console.log(handlePath::, imgPath)return new URL(handlePath, import.meta.url).href} catch (…

约束概念和分类、运用

约束的概念&#xff1a; 1. 约束是作用于表列上的规则&#xff0c;用于限制加入表的数据 2.约束的存在保证了数据库中数据的正确性&#xff0c;有效性和完整性。 约束的分类&#xff1a; 非空约束&#xff1a;NOT NULL 唯一约束&#xff1a;UNIQUE 主键约束&#xff1a;PRIMARY…

01-论文阅读-Deep learning for anomaly detection in log data: a survey

01-论文阅读-Deep learning for anomaly detection in log data: a survey 文章目录 01-论文阅读-Deep learning for anomaly detection in log data: a survey摘要I 介绍II 背景A 初步定义B 挑战 III 调查方法A 搜索策略B 审查的功能 IV 调查结果A 文献计量学B 深度学习技术C …

leetcode算法之分治-归并

目录 1.排序数组2.数组中的逆序对3.计算右侧小于当前元素的个数4.翻转对 1.排序数组 排序数组 //分治-归并 class Solution {int tmp[50010]; public:vector<int> sortArray(vector<int>& nums) {mergeSort(nums,0,nums.size()-1);return nums;}void mergeS…

线程池简介及其简单实现

如果需要频繁的创建销毁线程, 就需要想办法降低创建和销毁的开销, 而线程池就是一个很好的选择: 提前创建好一些线程, 等到需要使用线程的时候, 直接从池子里拿一个就好了, 当不再使用该线程时, 就放回到池子里. 那么此时就从 创建/销毁线程 -> 池子里取线程/将线程还到池子…

找不到vcruntime140_1.dll,无法继续执行代码怎么办?5个可以解决的方案分享

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“VCRuntime140_1.dll缺失”。这个错误通常会导致某些应用程序无法正常运行。为了解决这个问题&#xff0c;我们需要进行修复操作。本文将介绍5个修复VCRuntime140_1.dll缺失的方法&#xff…

解锁电力安全密码:迅软DSE助您保护机密无忧

电力行业信息化水平不断提高&#xff0c;明显提升了电力企业的生产运营能力&#xff0c;然而随着越来越多重要信息存储在终端计算机中&#xff0c;电力面临的信息安全挑战也越来越多。 作为关键基础设施的基础&#xff0c;电力企业各部门产生的资料文档涵盖着大量机密信息&…

微信小程序 prettier 格式化

一、安装prettier插件 二、打开设置 然后再打开setting.json 新增代码 {"editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","prettier.documentSelectors": ["**/*.wxml", "**/*.wx…

基于AVR单片机的移动目标视觉追踪系统设计与实现

基于AVR单片机的移动目标视觉追踪系统是一种常见的应用领域&#xff0c;旨在通过摄像头采集图像数据并使用图像处理和追踪算法实现对移动目标的实时追踪。本文将介绍基于AVR单片机的移动目标视觉追踪系统的设计原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 设计概述 …

革新突破!智能指标平台引领时代,国产大模型与企业级部署的完美结合

11月21日&#xff0c;跬智信息&#xff08;Kyligence&#xff09;圆满召开了线上数智论坛暨产品发布会&#xff0c;升级智能一站式指标平台 Kyligence Zen 及 AI 数智助理 Kyligence Copilot 的一系列企业级能力&#xff0c;包括正式支持智谱 AI、百川智能等在内的多款国产大模…

SVN创建分支

一 从本地创建方式可指定版本号进行分支创建。 1、在本地目录右击 -----> 点击branch/tag(分支/标签) From: 源&#xff0c;可指定具体的版本号&#xff0c; To path: 可通过"..."选择分支路径 最后点击确定&#xff0c;交由服务器执行创建。 二 通过SVN客…

List操作的一些常见问题

文章目录 阿里巴巴开发手册强制规约&#xff1a;1. Arrays.asList转换基本类型数组2. Arrays.asList返回的List不支持增删操作3. 对原始数组的修改会影响到我们获得的那个List4. ArrayList.subList强转ArrayList导致异常5. ArrayList中的subList切片造成OOM6.Copy-On-Write 是什…

上海亚商投顾:北证50指数大涨 机器人概念股掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡反弹&#xff0c;黄白二线有所分化&#xff0c;题材热点轮动表现。北证50指数大涨超3%&#…

「MACOS限定」 如何将文件上传到GitHub仓库

介绍 本期讲解&#xff1a;如何在苹果电脑上上传文件到github远程仓库 注&#xff1a;写的很详细 方便我的朋友可以看懂操作步骤 第一步 在电脑上创建一个新目录&#xff08;文件夹&#xff09; 注&#xff1a;创建GitHub账号、新建github仓库、git下载的步骤这里就不过多赘…

股票统计信息(七)

7-统计信息 文章目录 7-统计信息一. 股票周级别统计信息二. 查询可支持的所有的股票资金类型三. 股票图形统计信息四. 查询当前用户自选表里面最近十天的交易信息五. 查看天/星期范围统计的历史记录六. 查看最近多少天某个属性的涨跌幅度值 一. 股票周级别统计信息 接口描述: …