美文网首页Vue.js专区
element-ui NavMenut组件 与 Tabs组件

element-ui NavMenut组件 与 Tabs组件

作者: SevenDream | 来源:发表于2019-08-28 15:46 被阅读0次

    效果

    效果图

    所需工具

    vuex - 注:如果对vuex不熟悉的同学参考文章

    更新记录

    2020/4/15 新增sessionStorage 解决刷新后消失问题

    思路

    • 封装NavMenut组件组件及Tabs组件
    • 用 vuex 作为组件之间传值
    • router-view 放入 Tabs组件内
    • 使用 使用 Array.prototype.some()方法
      • 为了防止用户多次点击添加 做一个判断的值
      • 用 Array.prototype.some() 实现 Array.prototype.includes()

    具体代码

    具体思路和一些要点请看注释

    aside.vue(侧边栏组件)

    个人建议将 submenu 和 menu所需参数写成数据

    <template>
      <div class="zgz-admin-index-aside">
        <el-col :span="24">
          <div class="zgz-shop-avatar-name">
            <img class="avatar" src="~_img/timg.png" alt="追光者Aaron" />
            <p class="name">追光者Aaron</p>
          </div>
          <!--
            :default-active="$route.name" 
            获取router路由的name 对应menu-item内的index
            为了对应 tabs 的跳转点击 做选中
          -->
          <el-menu
            :default-active="$route.name" 
            class="el-menu-vertical-demo""
            background-color="#545c64"
            text-color="#fff"
            active-text-color="#ffd04b"
          >
            <!-- 循环数据格式 -->
            <el-submenu :index="`${index}`" v-for="(menu,index) in menuList" :key="index">
              <template slot="title">
                <i :class="menu.icont"></i>
                <span>{{menu.name}}</span>
              </template>
              <el-menu-item-group>
                <el-menu-item :index="item.routeName" v-for="item in menu.menuItem" :key="item.index" @click="handleOpen2(item)">{{item.name}}</el-menu-item>
              </el-menu-item-group>
            </el-submenu>
          </el-menu>
        </el-col>
      </div>
    </template>
    
    <script>
    import { mapActions } from 'vuex'
    export default {
      name: 'zgz-admin-index-aside',
      components: {},
      data() {
        return {
          // 将所需submenu,menu和tabs所需参数写成数据格式
          menuList: [
            {
              icont: 'el-icon-s-tools',
              name: '商店设置',
              menuItem: [
                {
                  title: '设置',
                  routeName: 'Setting',
                  name: '设置'
                },
                {
                  title: '小程序广告图',
                  routeName: 'WxAd',
                  name: '小程序广告图'
                }
              ]
            },
            {
              icont: 'el-icon-s-order',
              name: '订单',
              menuItem: [
                {
                  title: '订单管理',
                  routeName: 'orderList',
                  name: '订单管理'
                }
              ]
            }
          ]
        };
      },
      created() {},
      mounted() {},
      methods: {
        // 调用 注册vuex内注册的editableTabs方法
        ...mapActions({
          handleOpen2:'editableTabs'
        })
      }
    };
    </script>
    
    

    tabs.vue

    element 官方组件方法及方法没有注释

    <template>
        <div class=''>
            <el-tabs v-model="editableTabsValue" type="card" closable @tab-remove="removeTab" @tab-click="tabClick($event)">
                <el-tab-pane
                    :key="item.name"
                    v-for="item in editableTabs"
                    :label="item.title"
                    :name="item.name"
                >
                </el-tab-pane>
            </el-tabs>
            <router-view/> <!-- 放入router-view -->
        </div>
    </template>
    
    <script>
    export default {
      name: '',
      components: {},
      data() {
        return {
            
        };
      },
     mounted() {
        //刷新加载sessionStorage存着地址
        if (sessionStorage.getItem("tabsPage")) {
          this.$store.state.tabs.tabsPage = JSON.parse(
            sessionStorage.getItem("tabsPage")
          );
          var TabsValue = sessionStorage.getItem("TabsValue");
          this.$store.state.tabs.TabsValue = TabsValue;
          this.$router.push({ name: TabsValue });
        }
      },
      computed: {
        // 监听vuex保存的数据  
        editableTabs:{
           get(){
              return this.$store.state.tabsPage;
           },
           set(val){
              this.$store.state.tabsPage = val;
           }
        },
        editableTabsValue:{
           get(){
              return this.$store.state.TabsValue;
           },
           set(val){
              this.$store.state.TabsValue = val;
           }
        }
      },
      methods: {
          removeTab(targetName) {
            let tabs = this.editableTabs;
            let activeName = this.editableTabsValue;
            if (activeName === targetName) {
              tabs.forEach((tab, index) => {
                if (tab.name === targetName) {
                  let nextTab = tabs[index + 1] || tabs[index - 1];
                  console.log(nextTab);
                  if (nextTab) {
                    activeName = nextTab.name;
                  }
                }
              });
            }
            this.editableTabsValue = activeName;
            this.editableTabs = tabs.filter(tab => tab.name !== targetName);
            //解决刷新消失
            window.sessionStorage.setItem("tabsPage", JSON.stringify(newTabs));
            window.sessionStorage.setItem("TabsValue", activeName);
            // 删除时跳转不在停留被删除页
            this.$router.push({ name: activeName });
          }, 
          tabClick(event) {
            //写一个点击tabs跳转
            this.$router.push({ name: event.name });
          },
        }    
    };
    </script>
    
    
    vuex(store.js)

    重点来了!!!!

    import Vue from 'vue';
    import Vuex from 'vuex';
    // 引入 router 在vuex内使用router跳转
    import router from './router';
    
    Vue.use(Vuex);
    Vue.use(router);
    
    export default new Vuex.Store({
      state: { // 定义tabs 所需参数
        tabsPage: [],
        TabsValue: ''
      },
      mutations: {
        editableTabs: (state, obj) => {
          // 浅拷贝 state.tabsPage
          let arr = Array.from(state.tabsPage);
          // 判断数组内是否为空
          if (arr.length !== 0) {
            // 使用 Array.some 去判断是否存在对象信息
            var even = function(obj) {
              return arr.some(item => {
                return item.name === obj.routeName;
              });
            };
            // even方法 如果对象存在返回true,不存在则返回flase
            // 加!触发 true 代码块  
            if (!even(obj)/* 如果不存在将对象push进数组内bing */) {
              // 将tabs所需参数push进arr数组
              arr.push({ title: obj.name, name: obj.routeName });
              // 赋值给tabsPage参数
              state.tabsPage = arr;
              //存储sessionStorage -- 解决刷新消失
              window.sessionStorage.setItem("tabsPage", JSON.stringify(arr));
              window.sessionStorage.setItem("TabsValue", obj.routeName);
              // 赋值给TabsValue参数  
              state.TabsValue = obj.routeName;
              // 跳转 
              router.push({ name: obj.routeName });
            } else { // 如果存在 只做跳转选中
              // 赋值给TabsValue参数  
              state.TabsValue = obj.routeName;
              window.sessionStorage.setItem("TabsValue", obj.routeName);
              // 跳转 
              router.push({ name: obj.routeName });
            };
          } else {// 如果为0
            // 将tabs所需参数push进arr数组
            arr.push({
              title: obj.name, name: obj.routeName
            });
            // 赋值给tabsPage参数
            state.tabsPage = arr;
             // 赋值给TabsValue参数  
            state.TabsValue = obj.routeName;
             // 跳转 
            router.push({ name: obj.routeName });
          }
        }
      },
      actions: {
        // 注册方法
        editableTabs (context, obj) {
          context.commit('editableTabs', obj);
        }
      }
    });
    
    
    app.vue
    <template>
      <div class="admin">
        <el-container>
          <el-aside width="300px">
            <zgz-aside></zgz-aside> <!-- 我是侧边栏 -->
          </el-aside>
          <el-container>
            <el-header>
              <zgz-header></zgz-header>
            </el-header>
            <el-main>
              <zgz-tabs></zgz-tabs> <!-- 我是tabs组件 -->
            </el-main>
          </el-container>
        </el-container>
      </div>
    </template>
    

    后记

    如果有其他方法实现,欢迎一起讨论。

    最初开发想用Array.includes 去实现方法 但是对象数组无法去判断

    只能用Array.some 去实现Array.includes

    相关文章

      网友评论

        本文标题:element-ui NavMenut组件 与 Tabs组件

        本文链接:https://www.haomeiwen.com/subject/wzhpectx.html