vue如何实现el-menu与el-tabs联动,通过点击el-menu导航中的选项动态添加el-tabs页面

2023-11-04

Vue如何实现el-menu与el-tabs联动,通过点击el-menu导航中的选项动态添加tab页面

老规矩,先上效果图!
在这里插入图片描述
达成这个效果,首先我们先了解下原理

在el-menu中有一个属性router,开发文档中写的非常清晰,选择该属性后即开启路由跳转,即点击el-menu中的子选项后会进行页面跳转,但是你必须将需要跳转的路由地址写为跟组件的子路由地址,否则点击跳转后会直接跳向路由地址对应的页面,这样就失去了我们想要实现的效果

接下来说下el-tabs,它的构成规则大家可以去看一下饿了么ui(element-ui)开发文档中的模板说明,它里面的子元素都是通过遍历数组出来的,我给大家看下模板
在这里插入图片描述
所以明确这个,大家就应该有了思路

下面我讲下原理,首先我们需要一个全局变量用来存储即将要跳转的路由地址是什么,将其构建成一个数组,这里可以用BUS总线机制但更为简洁高效的方式是使用Vuex,关于Vuex的开发文档大家可以简单了解下,其实很简单,不要觉得麻烦

在这里插入图片描述

这是它的构造图,我们就将Vuex简单的理解为一个全局变量,可以看到他的整体走向,首先从State开始,State的作用就是一个仓库,用来存储你想要存取的数据,通过Dispatch方法将数据派遣到Actions进行一些操作,之后Actions再向Mutations提交完成转变

原理很简单,这里我们可以省区中间Actions的步骤,直接从State仓库向Mutations提交完成一系列的操作

好了,有了这个全局变量后,接下来的操作就一切清晰明了了,下面是整个demo的设计思路

点击el-menu中的子选项(将每个子选项的index值改为要跳转页面的路由地址,例:/page1) ==> 将这些地址存入Vuex中的State仓库 ==> el-tabs中el-tab-pane的循环数组变为当前的State仓库(当你引用vuex后,State仓库中的数据会逐一派发给各个组件) ==> 在Mutaition中写明方法,将要跳转的路由地址对应的页面设为激活项(即el-tab-pane中激活的页面)

这样一说大家是不是思路就很清晰了! 下面开始上代码

首先我将整个页面拆分成了两大组件,分别是左侧的LeftMenu,和右侧主体页面TabInner(其中包含了顶部的导航栏和下面el-tabs展示的页面)
先看LeftMenu的代码

<el-menu
      :default-active="$route.path"
      class="el-menu-vertical-demo"
      :collapse="isCollapse"
      background-color="#1F2D3D"
      text-color="#ffffff"
      router
    >
      <el-menu-item
        index="/page1"
        class="homePage"
        style="margin: 0 0 30px 0;"
      >
        <i class="iconfont" style="margin: 0 8px 0 0;">&#xe653;</i>
        <span slot="title">首页</span>
      </el-menu-item>
      <el-menu-item
        v-for="item of MenuList"
        :key="item.id"
        :index="item.index"
      >
        <i class="iconfont" style="margin: 0 8px 0 0;">{{item.icon}}</i>
        <span slot="title">{{item.content}}</span>
      </el-menu-item>
    </el-menu>

大家可以看到el-menu中添加了router选项,即开启了路由跳转地址,:default-active为什么要等于$route.path呢,是因为这样可以根据你跳转的地址来动态的切换激活选项,如果你设为定值,大家可以自行看下控制台的报错信息

里面循环的data数据

MenuList: [{
        index: '/page2',
        content: '数据目录管理',
        icon: '\ue619'
      },
      {
        index: '/page3',
        content: '数据产品管理',
        icon: '\ue625'
      }]

icon是iconfont中的,若想使用请翻看我博客中关于iconfont如何加入在v-for循环的数据中

首页我单独放在了一个el-menu-item中,剩下的子页面用循环展示

<el-menu-item
        index="/page1"
        class="homePage"
        style="margin: 0 0 30px 0;"
      >
        <i class="iconfont" style="margin: 0 8px 0 0;">&#xe653;</i>
        <span slot="title">首页</span>
</el-menu-item>

然后配置下路由地址,找到router.js或是模块化开发router文件夹下的index.js

{
      path: '/',
      component: Home,
      redirect: '/page1',
      children: [{
        path: '/page1',
        name: '首页',
        component: page1,
        meta: { title: '首页' }
      }, {
        path: '/page2',
        name: '数据目录管理',
        component: page2,
        meta: { title: '数据目录管理' }
      }, {
        path: '/page3',
        name: '数据产品管理',
        component: page3,
        meta: { title: '数据产品管理' }
      }]
    }

将这些子页面设为根路径下的子路由,并将页面重定向设置为/page1(即redirect: ‘/page1’),这样可以在打开项目的时候直接展示首页

下一步安装Vuex

npm i vuex --save

安装好后,我们开始配置
首先在src目录下新建一个store文件夹,在里面创建一个index.js
在这里插入图片描述
在里面配置,这里我就不过多叙述了,大家按着我的来就可以

import Vue from 'vue'
import Vuex from 'vuex'
/* eslint-disable */

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    openTab: [],
    activeIndex: ''
  },
  mutations: {
    add_tabs (state, data) {
      this.state.openTab.push(data)
    },
    delete_tabs (state, route) {
      let index = 0
      for (let gohh of state.openTab) {
        if (gohh.route === route) {
          break
        }
        index++
      }
      this.state.openTab.splice(index, 1)
    },
    set_active_index (state, index) {
      this.state.activeIndex = index
    }
  }
})

写完后在main.js中引入vuex,这样就可以将数据派发到各个组件上

import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './assets/iconfont/iconfont.css'
import store from './store/index.js'

Vue.use(ElementUI)

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

即把store引入,并在下面注册

做好这些后我简单说下store里面的index.js中文件的内容大概是什么意思

首先state仓库中分别存储了两个信息,一个是存放所有跳转路由地址的数组openTab,另一个是el-tab-pane哟弄个来展示当前激活页面的activeindex

那么mutations中存放的add_tabs是点击左侧el-menu中选项时触发的方法,即接受当前跳转的路由地址并将这一信息推入openTab这个数组中, 而delete_tabs则是将开启的tab标签关掉并设置下一激活项,set_active_index是设置激活项的方法

配置好这些以后,我们在tabInner组件中(即右侧主题内容组件)开始编写代码

首先书写计算属性computed,将el-tab-pane需要循环使用的openTab数组和展示激活项的activeIndex引入过来

computed: {
    openTab () {
      return this.$store.state.openTab
    },
    activeIndex: {
      get () {
        return this.$store.state.activeIndex
      },
      set (val) {
        this.$store.commit('set_active_index', val)
      }
    }
  }

之后在el-tabs中写入

<el-tabs
          v-model="activeIndex"
          type="card"
          @tab-click="clickTab"
          @tab-remove="removeTab"
          closable
        >
          <el-tab-pane
            v-for="item of openTab"
            v-if="openTab.length"
            :key="item.name"
            :label="item.name"
            :name="item.route"
          >
          </el-tab-pane>
        </el-tabs>

双向绑定activeIndex即可展示对应激活项

之后通过监听方法watch监听路由变化做事件处理

watch: {
    '$route' (to, from) {
      let flag = false
      for (let item of this.openTab) {
        if (item.name === to.name) {
          this.$store.commit('set_active_index', to.path)
          flag = true
          break
        }
      }

      if (!flag) {
        this.$store.commit('add_tabs', {route: to.path, name: to.name})
        this.$store.commit('set_active_index', to.path)
      }
      
    }
  }

这里为什么会定义一个值为布尔属性的变量flag呢,大家可以阅读下代码,意为,首先进行for循环,若此时openTab并未推入任何数据,是一个空数组,那么下面的if判断就不会成立,固flag不能变为true,从而进行下面的if(!flag)判断,若里面值为真才可进行其中的操作事件,此时flag仍未false,!flag即为true,我们提交两个方法,一个是当前路由地址推入state仓库中的openTab数组,另一个是设置el-tab-pane的激活项,即打开对应的页面

上面的话简单的可以理解为,若openTab中含有数据,那么我进行下面的判断,如果成立(意思就是左侧点击的导航项已经在el-tabs中打开了一个标签了,已经存在的页面就不会再打开了,直接进行页面的切换就可以了)然后flag变为true,并跳出循环,那么!flag就变成假了,下面的if判断也不会在做了。 但是如果openTab中并没有当前路由地址对应的页面信息,那么我就把这个信息存进去,并把el-tab-pane的激活项设置为他

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

同时我们也要再mounted中加入以下代码,这里写的很详细了,大家自行阅读下

做完这些后,我们需要把tab-click和tab-remove两个点击事件书写一下
首先是tab-click对应的方法clickTab

clickTab (tab) {
      this.$router.push({path: this.activeIndex})
      console.log(this.$route.path)
    }

点击事件后,直接推向当前对应的激活项

接下来是tab-remove对应的方法removeTab

removeTab (target) {
      if(target == '/'||target == '/page1'){
         return
       }
      this.$store.commit('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('set_active_index', this.openTab[this.openTab.length - 1].route)
          this.$router.push({path: this.activeIndex})
        }
      }
    }

第一个判断是保证首页不关,如果当前路径是根路径或者是我首页的路径,那么直接return结束当前函数

讲解了上面的代码后大家应该可以理解明白后边的代码了
自己阅读理解能更多的提升自己
做好这些操作就可以实现效果啦!样式大家可以自己去定义,只要按照这个思路走一遍就没问题啦

希望我们共同进步,互相提升! 有更好更高效的方法还望大佬不吝赐教!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue如何实现el-menu与el-tabs联动,通过点击el-menu导航中的选项动态添加el-tabs页面 的相关文章

随机推荐

  • python基础----06-----文件读写追加操作

    一 文件编码概念 思考 计算机只能识别 0和1 那么我们丰富的文本文件是如何被计算机识别 并存储在硬盘中呢 答案 使用编码技术 密码本 将内容翻译成0和1存入 常见编码有UTF8 gbk等等 不同的编码 将内容翻译成不同的二进制 二 文件的
  • (STM32CubeMX)超声波模块测距传感器学习笔记

    超声波模块HC SR04 一 简介 1 概念 2 电路连接 3 工作原理 二 STM32CubeMX配置步骤 1 芯片选择 2 引脚配置 3 时钟配置 4 其他配置 三 keil5代码 1 串口重定向 2 超声波模块编写 一 简介 1 概念
  • LVGL学习笔记6 - 输入设备

    目录 1 移植文件 2 移除多余代码 3 输入设备初始化 4 输入设备读回调函数 4 1 LV INDEV TYPE POINTER 4 2 LV INDEV TYPE KEYPAD 4 3 LV INDEV TYPE ENCODER 4
  • opencv SVM

    目录 What is a SVM 官方文档的源代码 函数补充 colRange 和 rowRange RNG 随机数 rng fill 简化 多分类问题 What is a SVM A Support Vector Machine SVM
  • Pytorch使用GPU

    Pytorch使用GPU pytorch默认是不使用gpu的 即使我们已经安装好了支持的cuda版本和cudnn 所以要使用gpu需要在程序里面设置一下 步骤 import torch use gpu torch cuda is avail
  • promise原理:代码实现

    基础代码 function window const PENDING pending const RESOLVED resolved const REJECTED rejected function Promise excutor this
  • 什么是模式识别,对抗学习是什么?

    模式识别是什么 作为人工智能的一个重要方向 模式识别的主要任务是模拟人的感知能力 如通过视觉和听觉信息去识别理解环境 又被称为 机器感知 或 智能感知 人们在观察事物或现象的时候 常常要寻找它与其他事物或现象的不同之处 并根据一定目的把相似
  • phpcms v9文件上传漏洞复现

    1 压缩包文件无递归删除 file FILES file 检查文件是否为空文件 if file exit 请勿上传空文件 name file name dir upload ext strtolower substr strrchr nam
  • 【牛客C++入门】CPP24 字符串拼接

    描述 键盘输入两个字符串 将这两个字符串进行拼接后输出 输入描述 键盘输入两个字符串 输出描述 输出两个字符串拼接后的结果 示例1 输入 hello nihao 输出 hellonihao 分析 使用函数getline 进行字符串拼接 代码
  • Linux安装之打开BIOS虚拟化支持

    打开BIOS虚拟化支持步骤 1 首先 你需要确认的使你的计算机型号和CPU BIOS的型号 因为过老的计算机是不支持虚拟化技术的 2 那么怎么知道呢 方法很简单 开机时按F2 F12 DEL ESC等键就可以进入到BIOS 这就需要根据电脑
  • HTTP Content-Disposition Explanation [ from MDN ]

    在常规的HTTP应答中 Content Disposition 消息头指示回复的内容该以何种形式展示 是以内联的形式 即网页或者页面的一部分 还是以附件的形式下载并保存到本地 在multipart form data类型的应答消息体中 Co
  • 集合拷贝几种常用方法

    一种简单的方式是通过构造方 List
  • 内网通 文件存服务器吗,内网通的服务器地址怎么看

    内网通的服务器地址怎么看 内容精选 换一换 介绍常见的安全组配置示例 如下示例中 出方向默认全通 仅介绍入方向规则配置方法 允许外部访问指定端口不同安全组内的弹性云服务器内网互通仅允许特定IP地址远程连接弹性云服务器SSH远程连接Linux
  • 运动控制中的安全机制——限位

    一 限位 运动控制器能够通过安装限位开关或者设置软限位来限制各轴的运动范围 一旦限位开关失效 将可能造成控制设备的损坏或发生生产事故 因此限位开关的稳定性和可靠性对于各种运动和位置控制设备来讲是十分重要的 限位限制一般有三重 软限位 限位开
  • Deepin深度操作系统中编译和安装dde-file-manager

    目录 一 Deepin环境准备 二 编译源码 1 从git仓库下载源码 2 安装第三方库依赖 2 1 可以直接apt install的库 2 2 安装Qt 2 3 安装deepin其他第三方库 3 编译安装 三 测试运行 参考 Deepin
  • 单片机开发

    作者主页 编程指南针 作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智
  • C# 中奇妙的函数–6. 五个序列聚合运算(Sum, Average, Min, Max,Aggregate)

    今天 我们将着眼于五个用于序列的聚合运算 很多时候当我们在对序列进行操作时 我们想要做基于这些序列执行某种汇总然后 计算结果 Enumerable 静态类的LINQ扩展方法可以做到这一点 就像之前大多数的LINQ扩展方法一样 这些是基于IE
  • 【Flutter 3-5】Flutter进阶教程——在Flutter中使用Lottie动画

    作者 弗拉德 来源 弗拉德 公众号 fulade me Lottie动画 在移动开发中总是需要展示一些动画特效 作为程序员的我们并不是很擅长用代码做动画 即便是有些动画可以实现 在跨平台的过程中也会因为API的差异性导致动画在各个平台中展示
  • VS2019企业版安装

    安装环境VMware Win7sp1 Net Framework 4 6 win7sp1update VS企业版下载地址 链接 https pan baidu com s 1ToBLr8sZJ9KbNKWG 6YREg 提取码 m9dr N
  • vue如何实现el-menu与el-tabs联动,通过点击el-menu导航中的选项动态添加el-tabs页面

    Vue如何实现el menu与el tabs联动 通过点击el menu导航中的选项动态添加tab页面 老规矩 先上效果图 达成这个效果 首先我们先了解下原理 在el menu中有一个属性router 开发文档中写的非常清晰 选择该属性后即