欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉詳細(xì)代碼

 更新時(shí)間:2023年10月12日 11:58:04   作者:嫣嫣細(xì)語  
這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉的相關(guān)資料,使用vue.js實(shí)現(xiàn)tab切換很簡(jiǎn)單,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下

1.實(shí)現(xiàn)效果

2.實(shí)現(xiàn)原理 

vuex,實(shí)現(xiàn)對(duì)當(dāng)前激活項(xiàng),當(dāng)前tab列表,當(dāng)前tab的translateX,當(dāng)前緩存頁,當(dāng)前路由的狀態(tài)管理。

將vuex中的數(shù)據(jù)保存到sessionStorage中,避免頁面刷新丟失,當(dāng)瀏覽器關(guān)閉時(shí),清空數(shù)據(jù)。

通過ref定位,拿到當(dāng)前窗口寬度與當(dāng)前所在路由的tab標(biāo)簽的所有寬度,判斷兩者,實(shí)現(xiàn)對(duì)多tab超出窗口寬度的處理。

當(dāng)點(diǎn)擊tab標(biāo)簽頁的時(shí)候,獲取相應(yīng)的激活項(xiàng),動(dòng)態(tài)的實(shí)現(xiàn)左側(cè)菜單欄的選中狀態(tài),用watch監(jiān)聽,updateActiveName和updateOpened。

當(dāng)關(guān)閉tab標(biāo)簽的時(shí)候,splice刪除當(dāng)前標(biāo)簽,若是刪除的最后一項(xiàng),跳轉(zhuǎn)到該項(xiàng)的前一項(xiàng)頁面。當(dāng)長(zhǎng)度為1時(shí),跳轉(zhuǎn)到首頁。

3.主要代碼

store.js

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
    state: {
        catch_components: [],
        activePath: '/index',
        openNames: [],
        activeName: "",
        tranx: "-0",
        tabList: [
            { path: '/index', label: '首頁', name: '首頁' }
        ]
    },
    mutations: {
        //清空vuex數(shù)據(jù)
        clearTabs(state) {
            state.catch_components = []
            state.activePath = '/homepage'
            state.openNames = []
            state.activeName = ""
            state.tranx = "-0"
            state.tabList = [
                { path: '/homepage', label: '首頁', name: 'home' }
            ]
        },
        // 跳轉(zhuǎn)頁面執(zhí)行
        selectMenu(state, submenu) {
            var activePath = submenu.path
            var oldTabList = state.tabList
            var result = oldTabList.some(item => {
                if (item.path === activePath) {
                    return true
                }
            })
            if (!result) {
                oldTabList.push({
                    path: submenu.path,
                    name: submenu.name,
                    label: submenu.label,
                    index: submenu.index,
                    subName: submenu.subName
                })
            }
            state.activePath = activePath
            state.tabList = oldTabList
            state.activeName = submenu.subName + "-" + submenu.index
            state.openNames = [submenu.subName]
        },
        // 添加keepalive緩存
        addKeepAliveCache(state, val) {
            if (val === '/homepage') {
                return
            }
            if (state.catch_components.indexOf(val) === -1) {
                state.catch_components.push(val)
            }
        },
        // 刪除keepalive緩存
        removeKeepAliveCache(state, val) {
            let cache = state.catch_components
            for (let i = 0; i < cache.length; i++) {
                if (cache[i] === val) {
                    cache.splice(i, 1);
                }
            }
            state.catch_components = cache
        },
        setTranx(state, val) {
            console.log(val)
            state.tranx = val
        },
        //關(guān)閉菜單
        closeTab(state, val) {
            state.activePath = val.activePath
            state.tabList = val.tabList
            state.openNames = val.openNames
            state.activeName = val.activeName
        },
        // 點(diǎn)擊標(biāo)簽選擇菜單
        changeMenu(state, val) {
            state.activePath = val.path
            state.activeName = val.subName + "-" + val.index
            state.openNames = [val.subName]
        }
    },
})

頁面代碼

computed: {
  ...mapState({
  activePath: (state) => state.activePath, // 已選中菜單
    tabList: (state) => state.tabList, // tags菜單列表
    catch_components: (state) => state.catch_components, // keepalive緩存
    openNames: (state) => state.openNames,
    activeName: (state) => state.activeName,
    tranx: (state) => state.tranx,
  }),
},
watch: {
   openNames() {
     this.$nextTick(() => {
       this.$refs.asideMenu.updateOpened();
     });
   },
   activeName() {
     this.$nextTick(() => {
       this.$refs.asideMenu.updateActiveName();
     });
   },
 },
handleClose(tab, index) {
  var oldOpenNames = this.$store.state.openNames,
    oldActiveName = this.$store.state.activeName,
    oldActivePath = this.$store.state.activePath,
    oldTabList = this.$store.state.tabList;
  let length = oldTabList.length - 1;
  for (let i = 0; i < oldTabList.length; i++) {
    let item = oldTabList[i];
    if (item.path === tab.path) {
      oldTabList.splice(i, 1);
    }
  }
  // 刪除keepAlive緩存
  this.$store.commit("removeKeepAliveCache", tab.path);
  if (tab.path !== oldActivePath) {
    return;
  }
  if (length === 1) {
    this.$store.commit("closeTab", {
      activePath: "/index",
      tabList: oldTabList,
    });
    this.$router.push({ path: oldTabList[index - 1].path });
    return;
  }
  if (index === length) {
    oldActivePath = oldTabList[index - 1].path;
    oldOpenNames = [oldTabList[index - 1].subName];
    oldActiveName =
      oldTabList[index - 1].subName + "-" + oldTabList[index - 1].index;
    this.$store.commit("closeTab", {
      activePath: oldActivePath,
      tabList: oldTabList,
      openNames: oldOpenNames,
      activeName: oldActiveName,
    });
    this.$router.push({ path: oldTabList[index - 1].path });
  } else {
    oldActivePath = oldTabList[index].path;
    oldOpenNames = [oldTabList[index].subName];
    oldActiveName =
      oldTabList[index].subName + "-" + oldTabList[index].index;
    this.$store.commit("closeTab", {
      activePath: oldActivePath,
      tabList: oldTabList,
      openNames: oldOpenNames,
      activeName: oldActiveName,
    });
    this.$router.push({ path: oldTabList[index].path });
  }
  this.getTrans(2);
},
changeMenu(item) {
  var oldActivePath = this.$store.state.activePath;
  if (oldActivePath === item.path) {
    return;
  }
  this.$store.commit("changeMenu", item);
  this.$router.push({ path: item.path });
  this.$nextTick(() => {
    this.getTrans(0);
  });
},
selectMenu(item, i, subName) {
  // 加入keepalive緩存
  this.$store.commit("addKeepAliveCache", item.path);
  var submenu = {
    path: item.path,
    name: item.title,
    label: item.title,
    index: i,
    subName: subName,
  };
  this.$store.commit("selectMenu", submenu);
  this.$router.push({ path: item.path });
  this.$nextTick(() => {
    this.getTrans(0);
  });
},
getTrans(e) {
  let width = 0;
  if (this.$refs.tags) {
    width = this.$refs.tags.clientWidth;
  }
  this.tabList.map((item, index) => {
    if (item.path === this.activePath) {
      this.currentIndex = index;
    }
    if (this.$refs[`tag${index}`] && this.$refs[`tag${index}`][0]) {
      this.$set(
        this.tabList[index],
        "width",
        this.$refs[`tag${index}`][0].$el.clientWidth + 4
      );
    }
  });
  let list = this.tabList.filter((item, index) => {
    return index <= this.currentIndex;
  });
  let totalWidth = list.reduce((total, currentValue) => {
    return total + Number(currentValue.width);
  }, 0);
  let totalAllWidth = this.tabList.reduce((total, currentValue) => {
    return total + Number(currentValue.width);
  }, 0);
  if (e == 0) {
    if (Number(width) > Number(totalWidth) || Number(width) == 0) {
      this.setTranx(-0);
      return false;
    }
    this.setTranx(Number(width) - Number(totalWidth) - 60);
  } else if (e == 1) {
    if (Number(width) > Number(totalAllWidth)) {
      return false;
    }
    this.setTranx(Number(width) - Number(totalAllWidth) - 60);
  } else {
    if (
      Number(width) > Number(totalAllWidth) &&
      this.$store.state.tranx < 0
    ) {
      this.setTranx(-0);
    }
  }
},
setTranx(val) {
  this.$store.commit("setTranx", val);
},
<Menu
  ref="asideMenu"
  :active-name="activeName"
  :open-names="openNames"
  accordion
  theme="light"
  :style="{ width: 'auto' }"
  :class="isCollapsed ? 'collapsed-menu' : 'menu-item'"
>
  <MenuItem
    @click.native="selectMenu({ path: '/index', title: '首頁' })"
    name="index"
    key="index"
  >
    <Icon type="ios-paw"></Icon>
    <span class="menuTitle">首頁</span>
  </MenuItem>
  <Submenu
    v-for="(item, index) in menuMap"
    :name="index"
    :key="index"
    class="sub_title"
  >
    <template slot="title">
      <svg class="icon" aria-hidden="true" v-if="item.fonticon">
        <use :xlink:href="item.fonticon" rel="external nofollow" ></use>
      </svg>
      <Icon :type="item.icon" v-else />
      <span class="menuTitle">{{ item.title }}</span>
    </template>
    <template v-if="item.children">
      <MenuItem
        v-for="(each, i) in item.children"
        :name="index + '-' + i"
        :key="index + '-' + i"
        @click.native="selectMenu(each, i, index)"
        ><span class="menuTitle">{{ each.title }}</span>
      </MenuItem>
    </template>
  </Submenu>
</Menu>
<Row class="head-tags">
  <div class="head-left left" @click="setTranx(0)">
    <Icon type="ios-rewind" size="30" color="#ffc0cb" />
  </div>
  <div class="tags-box">
    <div
      ref="tags"
      class="tags-box-scroll"
      :style="{ transform: `translateX(${tranx}px)` }"
    >
      <Tag
        :ref="'tag' + index"
        class="tags-item"
        :class="{ 'tags-item-active': activePath === item.path }"
        v-for="(item, index) in tabList"
        :key="index"
        :name="item.path"
        :closable="item.path !== '/index'"
        @click.native="changeMenu(item)"
        @on-close="handleClose(item, index)"
        >{{ item.label }}</Tag
      >
    </div>
  </div>
  <div class="head-left right" @click="getTrans(1)">
    <Icon type="ios-fastforward" size="30" color="#ffc0cb" />
  </div>
</Row>

總結(jié) 

到此這篇關(guān)于vue實(shí)現(xiàn)多個(gè)tab標(biāo)簽頁的切換與關(guān)閉的文章就介紹到這了,更多相關(guān)vue多個(gè)tab標(biāo)簽頁切換關(guān)閉內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 查找Vue中下標(biāo)的操作(some和findindex)

    查找Vue中下標(biāo)的操作(some和findindex)

    這篇文章主要介紹了查找Vue中下標(biāo)的操作(some和findindex),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • Vue SSR 組件加載問題

    Vue SSR 組件加載問題

    這篇文章主要介紹了Vue SSR 組件加載問題,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • 一個(gè)例子輕松學(xué)會(huì)Vue.js

    一個(gè)例子輕松學(xué)會(huì)Vue.js

    這篇文章主要為大家詳細(xì)介紹了一個(gè)例子,幫助大輕松學(xué)會(huì)Vue.js,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Vue組件庫ElementUI實(shí)現(xiàn)表格加載樹形數(shù)據(jù)教程

    Vue組件庫ElementUI實(shí)現(xiàn)表格加載樹形數(shù)據(jù)教程

    這篇文章主要為大家詳細(xì)介紹了Vue組件庫ElementUI實(shí)現(xiàn)表格加載樹形數(shù)據(jù)教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • vue獲取token實(shí)現(xiàn)token登錄的示例代碼

    vue獲取token實(shí)現(xiàn)token登錄的示例代碼

    最近新做了個(gè)vue項(xiàng)目,正好項(xiàng)目中有登錄部分,本文就詳細(xì)的介紹一下登錄部分的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),感興趣的小伙伴們可以參考一下
    2021-11-11
  • vue3中使用百度地圖的簡(jiǎn)單步驟

    vue3中使用百度地圖的簡(jiǎn)單步驟

    最近項(xiàng)目要用到百度地圖api,好久沒用到地圖,就百度了一番,下面這篇文章主要給大家介紹了關(guān)于vue3中使用百度地圖的簡(jiǎn)單步驟,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • vue使用keep-alive進(jìn)行組件緩存方法詳解(組件不緩存問題解決)

    vue使用keep-alive進(jìn)行組件緩存方法詳解(組件不緩存問題解決)

    keep-alive包裹動(dòng)態(tài)組件時(shí),會(huì)緩存不活動(dòng)的組件實(shí)例,而不是銷毀它們,下面這篇文章主要給大家介紹了關(guān)于vue使用keep-alive進(jìn)行組件緩存方法(組件不緩存問題解決)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • vue-loader和webpack項(xiàng)目配置及npm錯(cuò)誤問題的解決

    vue-loader和webpack項(xiàng)目配置及npm錯(cuò)誤問題的解決

    這篇文章主要介紹了vue-loader和webpack項(xiàng)目配置及npm錯(cuò)誤問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 詳解Vue 實(shí)例中的生命周期鉤子

    詳解Vue 實(shí)例中的生命周期鉤子

    這篇文章主要介紹了詳解Vue 實(shí)例中的生命周期鉤子,在Vue的整個(gè)生命周期中,它提供了一些生命周期鉤子,給了我們執(zhí)行自定義邏輯的機(jī)會(huì)。
    2017-03-03
  • vue關(guān)于自定義指令與v-if沖突的問題

    vue關(guān)于自定義指令與v-if沖突的問題

    這篇文章主要介紹了vue關(guān)于自定義指令與v-if沖突的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評(píng)論