Vue + Element-ui實現后台管理系統(3)---面包屑 + Tag標簽切換功能


面包屑 + Tag標簽切換功能

有關后台管理系統之前寫過兩遍博客,看這篇之前最好先看下這兩篇博客。另外這里只展示關鍵部分代碼,項目代碼放在github上: mall-manage-system

1、Vue + Element-ui實現后台管理系統(1) --- 總述

2、Vue + Element-ui實現后台管理系統(2)---項目搭建 + ⾸⻚布局實現

這篇主要講解 面包屑 + Tag標簽切換功能

整體效果



說明 從上面圖片可以看出,面包屑是在head部分組件里,Tag標簽雖然不再head部分組件里,但是它在整個管理后台系統中是會一直存在的,所以需要在Main.vue中。

這兩塊功能的實現,主要依賴Element-ui兩個樣式 Breadcrumb 面包屑 + Tag 標簽

一、面包屑功能 

1、背景

整個大致邏輯是這樣的,首先是面包屑 首頁 一定要存在的,接下來 側邊組件 點擊某菜單,把這個數據存到vuex中,然后 頭部組件 來獲取vuex中這個數據並展示。

2、CommonAside(側邊欄)

側邊欄需要做的就是當click當前菜單 就要把這個數據存儲到vuex中,為了頭部組件來獲取展示這份數據。

這里定義了一個click事件

    methods: {
    //跳轉路由 根據名稱跳轉
    clickMenu(item) {
      //調用vuex的selectMenu方法存儲數據
      this.$store.commit('selectMenu', item)
      //跳轉路由
      this.$router.push({ name: item.name })
    }
  }

3、CommonHeader(頭部組件)

因為面包屑是寫在CommonHeader中,所以這里展示這部分代碼

 <el-breadcrumb separator-class="el-icon-arrow-right">
                <!--很明顯 首頁 一定是存在的 所以這里直接寫死-->
                <el-breadcrumb-item :to="{ path: '/' }">首頁</el-breadcrumb-item>
                <!--第二級菜單名稱 就要看左側組件有沒有點擊指定菜單,沒有那就只顯示首頁 點擊就顯示當前菜單名稱-->
                <el-breadcrumb-item :to="current.path" v-if="current" >{{current.label}}</el-breadcrumb-item>
 </el-breadcrumb>

<script>
  //js部分
    import { mapState } from 'vuex'
    export default {
        computed: {
          //獲取vuex數據的另一種寫法
            ...mapState({
                current: state => state.tab.currentMenu
            })
        } 
    }
</script>

4、vuex配置

這里用了一個屬性為 currentMenu 的來存儲當前菜單信息

 state: {
    //當前菜單
    currentMenu: null,
  },
  mutations: {
    selectMenu(state, val) {
    //如果點擊應該是首頁的話 要把這份數據清空 因為頭部組件已經把首頁寫死了 只有點擊不是首頁菜單才存儲當前菜單
     val.name === 'home' ? (state.currentMenu = null) : (state.currentMenu = val)
    }
  },
}

這樣整個面包屑的功能就是實現了。


二、Tag標簽切換功能

1、背景

從上面效果來看,我們發現:

1、首頁的tag一開始就會存在,而且是不能進行刪除的
2、當點擊左側欄的時候,如果tag沒有該菜單名稱則新增,如果已經有了那么當前tag背景為藍色。
3、刪除當前tag,如果是最后一個,那么路由調整到它前面那個標簽並且背景變藍,如果不是最后一個那么路由調整到它后面那個標簽並且背景變藍。
4、還有我們注意這個tag不論路由如何切換都是會存在的,所以這個tag一定要存在我們之前定義的Main.vue中。

2、CommonTab.vue(標簽組件)

<template>
  <div class="tabs">
    <!--closable這里說明home是不能關閉的-->
    <el-tag
      :key="tag.name"
      size="small"
      v-for="(tag, index) in tags"
      :closable="tag.name !== 'home'"
      :disable-transitions="false"
      @close="handleClose(tag, index)"
      @click="changeMenu(tag)"
      :effect="$route.name === tag.name ? 'dark' : 'plain'"
    >
      {{ tag.label }}
    </el-tag>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'
export default {
  computed: {
      //獲取vuex的標簽集合數據
    ...mapState({
      tags: state => state.tab.tabsList
    })
  },
  methods: {
    ...mapMutations({
      close: 'closeTab'
    }),
    //關閉標簽
    handleClose(tag, index) {
      let length = this.tags.length - 1
      //vuex調方法的另一種寫法
      this.close(tag)
      // 如果關閉的標簽不是當前路由的話,就不跳轉
      if (tag.name !== this.$route.name) {
        return
      }
      // 關閉的標簽是最右邊的話,往左邊跳轉一個
      if (index === length) {
        this.$router.push({ name: this.tags[index - 1].name })
      } else {
        // 否則往右邊跳轉
        this.$router.push({ name: this.tags[index].name })
      }
    },

    //選擇標簽跳轉路由
    changeMenu(item) {
      this.$router.push({ name: item.name })
      this.$store.commit('selectMenu', item)
    }
  }
}
</script>

3、vuex配置

export default {

    //存儲數據
    state: {
        currentMenu: null,
        tabsList: [
            {
                path: '/',
                name: 'home',
                label: '首頁',
                icon: 'home'
            }
        ]
    },
    //調用方法
    mutations: {

        //選擇標簽 選擇面包屑
        selectMenu(state, val) {
            if (val.name === 'home') {
                state.currentMenu = null
            } else {
                state.currentMenu = val
                //如果等於-1說明tabsList不存在那么插入,否則什么都不做
                let result = state.tabsList.findIndex(item => item.name === val.name)
                result === -1 ? state.tabsList.push(val) : ''

            }
            // val.name === 'home' ? (state.currentMenu = null) : (state.currentMenu = val)
        },
        //關閉標簽
        closeTab(state, val) {
            let result = state.tabsList.findIndex(item => item.name === val.name)
            state.tabsList.splice(result, 1)
        },
    },
    actions: {}
}

4、Main.vue(主組件)

既然tag在整個后台都要顯示,那么就需要將CommonTab.vue加入到Main.vue中。

<template>
    <el-container style="height: 100%">
        <el-aside width="auto">
            <common-aside></common-aside>
        </el-aside>
        <el-container>
            <el-header>
                <common-header></common-header>
            </el-header>
            <!--加入CommonTab-->
            <common-tab></common-tab>
            <el-main>
                <router-view/>
            </el-main>
        </el-container>
    </el-container>
</template>

具體的看完整項目吧,最上面已經給了github地址了。



別人罵我胖,我會生氣,因為我心里承認了我胖。別人說我矮,我就會覺得好笑,因為我心里知道我不可能矮。這就是我們為什么會對別人的攻擊生氣。
攻我盾者,乃我內心之矛(14)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM