vue + element 實現快速關閉動態tabs功能

一隻小泰迪發表於2021-01-03

vue + element 實現快速關閉動態tabs功能

1.效果圖

在這裡插入圖片描述
樣式自行修改,如何製作動態導航欄,請參考我之前的文章,有一章專門記錄如何製作動態tabs,請參考系列文章

2.程式碼

commonTab.vue 動態tabs元件

<template>
  <div class="common-tab">
    <div class="tab-menu">
      <div>
        <el-tag
          :key="tag.url"
          v-for="tag in tags"
          :closable="tag.url !== 'home'"
          :disable-transitions="false"
          @click="changeMenu(tag)"
          @close="handleClose(tag)"
          :effect="$route.name === tag.url ? 'dark' : 'plain'"
        >
          <i :class="tag.logo"></i>
          {{ tag.name }}
        </el-tag>
      </div>
    </div>

    <div class="refresh-btn">
      <!-- <i class="el-icon-refresh">重新整理</i> -->
      <el-dropdown size="small" @command="handleCommand">
        <span class="el-dropdown-link">快速關閉<i class="el-icon-arrow-down"></i> </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="closeUpPage">關閉左側 <i class="el-icon-close"></i></el-dropdown-item>
          <el-dropdown-item command="closeDownPage">關閉右側 <i class="el-icon-close"></i></el-dropdown-item>
          <el-dropdown-item command="closeOtherPage">關閉其他 <i class="el-icon-close"></i></el-dropdown-item>
          <el-dropdown-item command="closeAllPage">關閉所有 <i class="el-icon-close"></i></el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <el-button type="primary" icon="el-icon-refresh" class="refresh" size="mini" @click="refresh">重新整理</el-button>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  data() {
    return {}
  },
  created() {
    // 獲取重新整理之前獲取路由的資訊
    const sessionTabs = JSON.parse(sessionStorage.getItem('tabs'))
    if (sessionTabs !== null) {
      // 獲取到儲存的路由列表之後,將資訊利用vuex進行儲存
      this.$store.commit('changeSetTabs', sessionTabs.tabList)
    }
  },
  mounted() {
    // 重新整理之前儲存路由資訊
    window.addEventListener('beforeunload', e => {
      sessionStorage.setItem(
        'tabs',
        JSON.stringify({
          tabList: this.tags,
          activeTab: this.$route.name
        })
      )
    })
  },
  computed: {
    ...mapState({
      tags: state => state.tab.tabList
    })
  },
  methods: {
    // 快速關閉
    handleCommand(command) {
      // 關閉左側
      if (command === 'closeUpPage') {
        if (this.$route.name !== 'home') {
          this.tags.forEach((item, index) => {
            if (item.url === this.$route.name && this.tags[index - 1].url !== 'home') {
              const nextTab = this.tags[index]
              this.$store.commit('selectMenu', nextTab)
              this.$router.push({ name: nextTab.url })
              this.$store.commit('closeTab', this.tags[index - 1])
            }
          })
        }
      }
      // 關閉右側
      if (command === 'closeDownPage') {
        this.tags.forEach((item, index) => {
          if (item.url === this.$route.name && this.tags[index + 1] !== undefined) {
            const nextTab = this.tags[index]
            this.$store.commit('selectMenu', nextTab)
            this.$router.push({ name: nextTab.url })
            this.$store.commit('closeTab', this.tags[index + 1])
          }
        })
      }
      // 關閉其他
      if (command === 'closeOtherPage') {
        this.tags.forEach((item, index) => {
          if (item.url === this.$route.name) {
            const nextTab = this.tags[index]
            this.$store.commit('colseAllTab', 'closeAll')
            this.$store.commit('selectMenu', nextTab)
            this.$router.push({ name: nextTab.url })
          }
        })
      }
      // 關閉所有
      if (command === 'closeAllPage') {
        this.$store.commit('colseAllTab', 'closeAll')
        this.$router.push({ name: 'home' })
      }
    },
    // 點選切換頁面方法
    changeMenu(item) {
      this.$router.push({ name: item.url })
      this.$store.commit('selectMenu', item)
    },
    // 關閉介面的方法
    handleClose(tag) {
      this.tags.forEach((item, index) => {
        if (item.url === tag.url && tag.url === this.$route.name) {
          const nextTab = this.tags[index + 1] || this.tags[index - 1]
          if (nextTab) {
            this.$store.commit('selectMenu', nextTab)
            this.$router.push({ name: nextTab.url })
          }
        } else {
          this.$router.push({ name: this.$route.name })
        }
      })
      this.$store.commit('closeTab', tag)
    },
    // 重新整理方法
    refresh() {
      window.location.reload()
    }
  }
}
</script>

<style lang="scss" scoped>
@import '~@/assets/scss/common/tab.scss';
</style>

store目錄(vuex)下的 tab.js

export default {
  state: {
    isCollapse: false,
    currentMenu: {}, // 左側選擇當前的路由
    tabList: [
      {
        permissionkey: 'home',
        url: 'home',
        name: '首頁',
        logo: 'iconfont icon-shouye'
      }
    ] // tabs列表
  },
  mutations: {
    // 根據左側導航欄設定tabList的值
    selectMenu(state, val) {
      if (val.url !== 'home') {
        state.currentMenu = val
        const result = state.tabList.findIndex(item => item.url === val.url)
        if (result === -1) {
          state.tabList.push(val)
        }
      } else {
        state.currentMenu = null
      }
    },
    // 關閉tab方法
    closeTab(state, val) {
      const result = state.tabList.findIndex(item => item.url === val.url)
      state.tabList.splice(result, 1)
    },
    // 關不tabs所有的方法或者關閉其他
    colseAllTab(state, val) {
      if (val === 'closeAll') {
        state.tabList = [
          {
            permissionkey: 'home',
            url: 'home',
            name: '首頁',
            logo: 'iconfont icon-shouye'
          }
        ]
      }
    },
    // 重新整理頁面之後存進來的值
    changeSetTabs(state, val) {
      state.tabList = val
    },
    // 控制關閉/開啟摺疊左側導航事件
    collapseMenu(state) {
      state.isCollapse = !state.isCollapse
    }
  },

  actions: {}
}

相關文章