Vue路由+Tab元件實現多頁籤功能

洛陽醉長安行發表於2022-11-24

在vue單頁面應用中,當點選導航選單時會切換路由,一般是在中間的router-view路由檢視中直接顯示對應路由的頁面元件,那麼本編就介紹一下如何使用vue路由配合tab元件實現多頁籤功能,開啟一個新的選單路由時變成彈出一個新的tab頁籤,並且隨時可以切換到之前的頁面,保留之前的元件狀態。

image.png

當前開啟的tab需要在data中以一個陣列的方式維護(openTab),預設顯示首頁
main.vue:

     openTab: [
        {
          title: "首頁",
          name: "/Index", //路由
          closable: false, //首頁不可關閉
          componentName: "index" //元件名稱用於keepalive快取
        }
      ],

componentName是對應tab中頁面元件的name值,所以每一個元件都必須設定自己的name值。

image.png
下面看template如何實現,首先加入elementUItab元件:

      <div
        id="main-home"
      >
        <el-tabs
          @tab-remove="removeTab"
          v-model="activeIndex"
          type="card"
          class="main-tab"
          @tab-click="clickTab"
        >
          <el-tab-pane
            :key="item.name"
            v-for="item in openTab"
            :label="item.title"
            :name="item.name"
            :closable="item.closable"
          ></el-tab-pane>
        </el-tabs>
        <div class="view-container">
          <keep-alive :include="openTab.map(i => i.componentName)">
            <router-view v-if="isRouterAlive"></router-view>
          </keep-alive>
        </div>
      </div>

注意router-view並沒有放在el-tab-pane中,而是抽到了外面,tab共用這一塊試圖,因為如果使用了多試圖的方式會出現元素id屬性可能相同的問題。同時使用keep-alive快取元件的狀態。
可以使用include儲存當前tab的元件名name列表實現tab檢視的快取,這樣互相切換就不需要重新載入元件,但是要特別注意元件的name的唯一。

removeTab刪除時遍歷找到對應的tab,然後把當前啟用的activeIndex設定到當前tab的下一個或上一個
methods:

 removeTab(target) {
      // 刪除的是當前選中的頁面
      if (this.activeIndex === target) {
        this.openTab.forEach((item, index) => {
          if (item.name == target) {
            let nextTab = item[index + 1] || item[index - 1];
            if (nextTab) {
              this.activeIndex = nextTab.name;
            }
          }
        });
      }
      var i = 0;
      this.openTab.forEach((item, index) => {
        if (item.name == target) {
          return (i = index);
        }
      });
      this.openTab.splice(i, 1);

      // 更新路由
      this.$router.push({ path: this.openTab[this.openTab.length - 1].name });
    },

    clickTab(tab) {
      this.activeIndex = tab.paneName;
      this.$router.push({ path: this.activeIndex });
    },



  watch: {
    $route(to, form) {
      //當路由更新進行tab切換
      var flag = false;
      // 當前頁面選單已開啟,直接切換過去
      if (this.openTab) {
        for (let i = 0; i < this.openTab.length; i++) {
          if (
            to.path == this.openTab[i].name || to.path.includes(this.openTab[i].name)
          ) {
            //openTab中已存在?
            this.activeIndex = this.openTab[i].name;
            flag = true;
            break;
          }
        }
      }

      // 開啟新的頁面tab
      if (!flag) {
        let obj = {
          title: to.meta.title,
          name: to.path,
          closable: true,
          componentName: to.matched[1].components.default.name //路由只快取到第1層,更深層的檢視不考慮
        };
        this.activeIndex = to.path;
        this.openTab.push(obj);
      }
    },
  }

透過watch監測路由的變動對tab進行處理,也是遍歷找到對應的tab進行切換,當路由切換時不僅route-view會進行改變,tab也會跟著更新。
注意當點選導航開啟的一個新的路由時需要新增新的tab,同時需要從當前路由配置中拿出對應頁面的元件名name儲存到componentName中,這裡拿取第一層是因為目前不考慮多級路由情況的。

以上就是本編文章的所有內容了,重點有建立tab和檢視,實現刪除功能,到最後的watch方式監聽路邊來切換tab,詳細說明了實現過程,如果你覺得好的話可以關注我,共同努力,共同進步。我目前是堅持每月都會發布前端相關文章。感謝~

相關文章