2020-10-14 vue element-ui 实现 tabs 动态添加删除

这里我使用的路由嵌套解决方案

page.vue
<template>
  <div class="home">
    <el-container>
      <el-menu
        :default-active="this.$route.path"
        class="el-menu-vertical-demo"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b"
        @open="handleOpen"
        @close="handleClose"
        :collapse="isCollapse"
      >
        <!--logo-->
        <el-submenu class="logo-min" index="1">
          <template slot="title">
            <i v-show="isCollapse" class="el-icon-setting"></i>
            <el-image class="logo" v-show="!isCollapse" :src="logo" fit="contain"></el-image>
          </template>
          <el-menu-item-group>
            <span slot="title">超级管理员</span>
            <el-menu-item index="#">个人资料</el-menu-item>
            <el-menu-item index="#">联系我们</el-menu-item>
            <el-menu-item index="#" @click="handleCommand">安全退出</el-menu-item>
          </el-menu-item-group>
        </el-submenu>

        <!--动态菜单-->
        <el-submenu v-for="(item, i) in navList" :key="i" :index="item.id">
          <template slot="title">
            <i :class="item.icon"></i>
            <span slot="title">{{ item.name }}</span>
          </template>
          <el-menu-item-group v-for="(ite, i) in item.son" :key="i">
            <el-menu-item @click="handleLink({ name: ite.name, path: ite.path,id: ite.id })" :index="ite.path">{{ ite.name }}</el-menu-item>
          </el-menu-item-group>
        </el-submenu>
      </el-menu>

      <!--右侧-->
      <el-container>
        <!--导航-->
        <el-header class="head">
          <el-radio-group class="isCollapse" v-model="isCollapse">
            <el-radio-button v-show="isCollapse" :label="false"><i class="el-icon-s-unfold"></i></el-radio-button>
            <el-radio-button v-show="!isCollapse" :label="true"><i class="el-icon-s-fold"></i></el-radio-button>
          </el-radio-group>

          <el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="link">
            <el-tab-pane v-for="item in editableTabs" :key="item.index" :label="item.name" :name="item.path"></el-tab-pane>
          </el-tabs>


        </el-header>

        <!--内容-->
        <el-main><router-view /></el-main>

        <el-footer>Author:liming &nbsp;&nbsp;&nbsp;&nbsp; 版本:1.0.1 &nbsp;&nbsp;&nbsp;&nbsp;版权所有:创新工场</el-footer>
      </el-container>
    </el-container>
  </div>
</template>

<script>
// @ is an alias to /src
import logo from '../../assets/admin_logo.png';
//import { getListAPI } from '../../api/api.js';
export default {
  computed: {
    key() {
      return this.$route.path;
    }
  },
  data() {
    return {
      logo: logo,
      isCollapse: false,
      iconHid: false,
      navList: [
        {
          id: '2',
          name: '商品',
          icon: 'el-icon-location',
          path: '',
          son: [
            {
              id: '4',
              number: '2-1',
              name: '商品管理',
              icon: '',
              path: '/about'
            },
            {
              id: '5',
              number: '2-2',
              name: '商品分类',
              icon: '',
              path: '2'
            },
            {
              id: '6',
              number: '2-3',
              name: '商品规格',
              icon: '',
              path: '3'
            },
            {
              id: '7',
              number: '2-4',
              name: '商品评价',
              icon: '',
              path: '4'
            }
          ]
        },
        {
          id: '3',
          name: '会员',
          icon: 'el-icon-document',
          path: '',
          son: [
            {
              id: '8',
              number: '3-1',
              name: '会员管理',
              icon: '',
              path: '/list'
            },
            {
              id: '9',
              number: '3-2',
              name: '会员等级',
              icon: '',
              path: '5'
            },
            {
              id: '10',
              number: '3-3',
              name: '会员分组',
              icon: '',
              path: '6'
            },
            {
              id: '11',
              number: '3-3',
              name: '抽奖列表',
              icon: '',
              path: '7'
            }
          ]
        }
      ],
      editableTabsValue: '商品管理',
      editableTabs: [],

    };
  },
  methods: {
    onSubmit() {
      console.log('submit!');
    },
    handleOpen(key, keyPath) {
      console.log(key);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    },

    handleLink(data) {
      this.addTab(data);
    },
    /**
     * 注销
     */
    handleCommand() {
      localStorage.removeItem('Authorization');
      localStorage.removeItem('refresh_token');
      localStorage.removeItem('appId');
      console.log(localStorage.getItem('Authorization'));
      this.$router.go(0);
    },
    /**
     * 添加tab
     * @param {Object} targetName
     *
     *
     */
    addTab(targetName) {
      let that = this;
      that.editableTabs.push(targetName);
      // 数组去重
      let hash = {};
      that.editableTabs = that.editableTabs.reduce((item, next) => {
        if (hash[next.name] ? '' : hash[next.name] = true) {
          item.push(next);
        }
        return item;
      }, []);
      if(that.editableTabsValue!=targetName.path){
        that.$router.push({path:targetName.path})
        that.editableTabsValue = targetName.path;
      }
    },
    /**
     * 删除tab
     * @param {Object} targetName
     */
    removeTab(targetName) {
      let tabs = this.editableTabs;
      let activeName = this.editableTabsValue;
      if (activeName === targetName) {
        tabs.forEach((tab, index) => {
          if (tab.path === targetName) {
            let nextTab = tabs[index + 1] || tabs[index - 1];
            if (nextTab) {
              activeName = nextTab.name;
            }
          }
        });
      }
      this.editableTabsValue = targetName;
      this.editableTabs = tabs.filter(tab => tab.path !== targetName);
    },
    /**
     * 点击切换路由
     * @param {Object} tab
     *
     */
    link(tab) {
      this.$router.push(tab.name);
    }
  }
};
</script>
<style>
.home {
  height: 100%;
}
.el-container {
  height: 100%;
}
.el-header,
.el-footer {
  color: #333;
  text-align: center;
  line-height: 3rem;
}
.head {
  height: 3rem !important;
}

.el-aside {
  background-color: #304156;
  color: #fff;
  text-align: center;
  height: 100%;
}
.el-main {
  background-color: #e9eef3;
  color: #333;
  text-align: center;
  line-height: 160px;
}

.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
.el-menu-item {
  overflow: hidden;
}

.logo-min {
  overflow: hidden;
}

.logo-min .el-icon-arrow-down {
  display: none;
}
.logo {
  width: 88%;
  margin: 0.5rem 6%;
}

.user {
  padding-left: 20px;
}
.user span {
  color: #c0c4cc;
}
.isCollapse {
  float: left;
}
.isCollapse span {
  background: none;
  border: none !important;
  padding: 12px 0;
}
.isCollapse i {
  font-size: 1.3rem;
}
</style>

router/index
{
    path: '/',
    name: 'Page',
    component: Page,
    children: [{
        path: 'about', //以“/”开头的嵌套路径会被当作根路径,所以子路由上不用加“/”;在生成路由时,主路由上的path会被自动添加到子路由之前,所以子路由上的path不用在重新声明主路由上的path了。
        name: 'About',
        component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
      },
      {
        path: 'list', //以“/”开头的嵌套路径会被当作根路径,所以子路由上不用加“/”;在生成路由时,主路由上的path会被自动添加到子路由之前,所以子路由上的path不用在重新声明主路由上的path了。
        name: 'List',
        component: () => import( /* webpackChunkName: "about" */ '../views/List.vue')
      },
    ]
  },
文件结构
image.png
about 页面示例
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容