vue - element ui 实现 tab 选项卡的动态增删

注意 this.$refs.tabs[i] 的属性对应

参考的原帖貌似是没对应好。
本人在使用时出现几个问题:

  • title无法显示
  • 只能添加一个tab
  • tab会重复添加
  • 默认打开的首页也能再创建
  • 修改之后,功能正常。
<template>
  <el-tabs v-model="activeTab" type="card"
           @tab-remove="removeTab" @tab-click="tabClick">
    <el-tab-pane v-for="(item, index) in tabsItem"
                 :key="item.name"
                 :label="item.title"
                 :name="item.name"
                 :closable="item.closable"
                 :ref="item.ref">
    </el-tab-pane>
  </el-tabs>
</template>

<script>

export default {
  name: "Tabs",
  data() {
    return {
      activeTab: '1', //默认显示的tab
      tabIndex: 1,  //tab目前显示数
      tabsItem: [{
        title: '库存预警',
        name: '1',
        closable: false,
        ref: 'tabs',
      }],
      tabsPath: [{
        name: "1",
        path: '/index'
      }]
    }
  },
  watch: {
    // 监听路由的变化,动态生成tabs
    '$route': function (to) {
      // 判断是否需要新增页面
      let flag = true;
      const path = to.path;
      if (Object.keys(to.meta).length !== 0) {
        for (let i = 0; i < this.$refs.tabs.length; i++) {
          // 如果页面已存在,则直接定位当页面,否则新增tab页面
          if (this.$refs.tabs[i].label === to.meta.title) {
            //定位到已打开页面
            this.activeTab = this.$refs.tabs[i].name;
            flag = false;
            break;
          }
        }
        // 新增页面
        if (flag) {
          // 获得路由元数据的name和组件名
          const thisName = to.meta.title
          // const thisComp = to.meta.comp
          //对tabs的当前激活下标和tabs数量进行自加
          let newActiveIndex = ++this.tabIndex + '';
          // 动态双向追加tabs
          this.tabsItem.push({
            title: thisName,
            name: String(newActiveIndex),
            closable: true,
            ref: 'tabs',
          })
          this.activeTab = newActiveIndex;
          // 后面需要得到当前tabs的时候可以通过当前tabs的name获得path
          if (this.tabsPath.indexOf(path) === -1) {
            this.tabsPath.push({
              name: newActiveIndex,
              path: path
            })
          }
        }
      }
    }
  },
  methods: {
    removeTab(targetName) { //删除Tab
      let tabs = this.tabsItem; //当前显示的tab数组
      let activeName = this.activeTab; //点前活跃的tab
      //如果当前tab正活跃 被删除时执行
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.name === targetName) {
            let nextTab = tabs[index + 1] || tabs[index - 1];
            if (nextTab) {
              activeName = nextTab.name;
              this.tabClick(nextTab);
            }
          }
        });
      }
      this.activeTab = activeName;
      this.tabsItem = tabs.filter(tab => tab.name !== targetName);
      //在tabsPath中删除当前被删除tab的path
      this.tabsPath = this.tabsPath.filter(item => item.name !== targetName)
    },
    tabClick(thisTab) {
      /*
      * thisTab:当前选中的tabs的实例
      * 通过当前选中tabs的实例获得当前实例的path 重新定位路由
      * */
      let val = this.tabsPath.filter(item => thisTab.name === item.name)
      this.$router.push({
        path: val[0].path
      })
    }
  },
  mounted() {
    /*
    * 监听页面刷新事件
    * 页面刷新前 需要保存当前打开的tabs的位置,刷新后按刷新前的顺序展示
    * 使用js的sessionStorage保存刷新页面前的数据
    * */
    window.addEventListener('beforeunload', e => {
      sessionStorage.setItem("tabsItem", JSON.stringify({
        currTabsItem: this.tabsItem.filter(item => item.name !== "1"),
        currTabsPath: this.tabsPath.filter(item => item.name !== "1"),
        currActiveTabs: this.activeTab,
        currIndex: this.tabIndex
      }))
    });
  },
  created() {
    // 使用js的sessionStorage读取刷新前的数据,并按刷新前的tabs顺序重新生成tabs
    const sessionTabs = JSON.parse(sessionStorage.getItem("tabsItem"))
    if (sessionTabs.currTabsItem.length !== 0 && sessionTabs.currTabsPath.length !== 0) {
      for (let i = 0; i < sessionTabs.currTabsItem.length; i++) {
        this.tabsItem.push({
          title: sessionTabs.currTabsItem[i].title,
          name: sessionTabs.currTabsItem[i].name,
          closable: true,
          ref: sessionTabs.currTabsItem[i].ref,
          content: sessionTabs.currTabsItem[i].content
        })
      }
      for (let j = 0; j < sessionTabs.currTabsPath.length; j++) {
        this.tabsPath.push({
          name: sessionTabs.currTabsPath[j].name,
          path: sessionTabs.currTabsPath[j].path
        })
      }
      this.activeTab = sessionTabs.currActiveTabs
      this.tabIndex = sessionTabs.currIndex
      // 避免强制修改url 出现浏览器的url输入框的路径和当前tabs选中的路由路径不匹配
      const activePath = this.tabsPath.filter(item => item.name === this.activeTab)
      this.$router.push({
        path: activePath[0].path
      })
    }
  },
}
</script>

<style scoped>
/deep/ .el-tabs__header {
  margin: 0;
}
</style>

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
element-ui实现tab选项卡的基本用法可以通过el-tabs和el-tab-pane组件来实现。首先,需要在data中定义一个变量来控制当前选中的标签页,然后使用v-model指令将el-tabs的value属性与该变量进行绑定。接下来,在el-tabs中使用v-for指令遍历标签页,并使用el-tab-pane组件来创建每个标签页。在el-tab-pane中,使用:label属性来设置标签页的标题,使用:name属性来设置标签页的唯一标识符。最后,可以在el-tab-pane的内容区域插入需要显示的内容。 对于自定义标签页样式,可以使用插槽来实现。在el-tab-pane中,可以使用slot="label"来定义一个插槽,然后在插槽中编写自定义的标签页内容,可以包含任意的HTML元素和Vue指令。 下面是具体的代码示例: ```html <template> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane v-for="item in tabs" :label="item.count ? item.title + ' ' + item.count : item.title" :name="item.value" :key="item.id"> <div slot="label"> <span class="key">{{ item.title }}</span> <span class="value" v-if="item.count">{{ item.count }}</span> </div> {{ item.id }} </el-tab-pane> </el-tabs> </template> <script> export default { data() { return { activeName: "first", tabs: [ { title: "消息", value: "first", count: 3, id: 1 }, { title: "待办", value: "second", count: 4, id: 2 }, { title: "角色管理", value: "third", id: 3 } ] }; }, methods: { handleClick(tab, event) { console.log(tab, event); } } }; </script> <style scoped> .value { color: #ff0000; font-size: 16px; } </style> ``` 以上代码实现了一个基本的tab选项卡,每个标签页都有一个标题和一个可选的数字,点击标签页会触发handleClick方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值