溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

發(fā)布時(shí)間:2022-03-03 14:57:01 來(lái)源:億速云 閱讀:172 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史”這篇文章吧。

廢話

demo預(yù)覽

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

實(shí)現(xiàn)的功能

默認(rèn)有首頁(yè),不能關(guān)閉

點(diǎn)擊路由菜單,判斷有無(wú)存在,沒有就添加,有就定位到上面

點(diǎn)擊跳轉(zhuǎn),點(diǎn)擊X可關(guān)閉

關(guān)閉當(dāng)前頁(yè),自動(dòng)跳到下一個(gè)tag頁(yè)面

如果當(dāng)前頁(yè)在最后一個(gè),默認(rèn)跳到上一個(gè)tag頁(yè)面

右鍵菜單,刷新,關(guān)閉右側(cè),關(guān)閉所有

動(dòng)態(tài)判斷tags長(zhǎng)多,放不下時(shí),出現(xiàn)左右兩側(cè)按鈕,減少時(shí)自動(dòng)消失

動(dòng)態(tài)判斷窗口放大縮小,自動(dòng)判斷有無(wú)左右兩側(cè)按鈕

正文

不用任何vuex,亂七八糟的方法,全在一個(gè)文件,粘貼即用

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

放到你想要的位置即可(此demo,放在了面包屑上面)

先安裝 (監(jiān)聽某dom元素大小的包)

npm install element-resize-detector

tags.vue

<template>
  <div>
    <div class="tags">
      <!-- 左箭頭 -->
      <div
        class="arrow arrow_left"
        v-show="arrowVisible"
        @click="handleClickToLeft"
      >
        <i class="el-icon-arrow-left"></i>
      </div>
      <!-- 標(biāo)簽內(nèi)容 -->
      <div class="tags_content" ref="box">
        <span ref="tags">
          <el-tag
            v-for="(tag, index) in tags"
            :key="tag.name"
            :class="[active == index ? 'active top_tags' : 'top_tags']"
            effect="dark"
            :closable="tag.name != 'Firstpage1'"
            @close="handleClose(index, tag)"
            @click="clickTag(index, tag)"
            @contextmenu.native.prevent="handleClickContextMenu(index, tag)"
          >
            {{ $t("router." + tag.name) }}
          </el-tag>
        </span>
      </div>
      <!-- 右箭頭 -->
      <div
        class="arrow arrow_right"
        v-show="arrowVisible"
        @click="handleClickToRight"
      >
        <i class="el-icon-arrow-right"></i>
      </div>
    </div>
    <!-- 右鍵菜單 -->
    <ul
      v-show="contextMenu.isShow"
      :
      class="el-dropdown-menu el-popper"
      x-placement="bottom-end"
    >
      <li
        v-if="this.active == this.contextMenu.index"
        class="el-dropdown-menu__item"
        @click="refresh"
      >
        刷新
      </li>
      <li class="el-dropdown-menu__item" @click="closeRightTag">
        關(guān)閉右側(cè)
      </li>
      <li class="el-dropdown-menu__item" @click="closeOtherTag">
        關(guān)閉其它
      </li>
      <div x-arrow="" class="popper__arrow" ></div>
    </ul>
  </div>
</template>

<script>
import elementResizeDetectorMaker from "element-resize-detector";
export default {
  data() {
    return {
      // 是否有箭頭
      arrowVisible: true,
      // 點(diǎn)擊次數(shù)
      num: 0,
      active: 0,
      tags: [],
      // 右鍵的元素
      contextMenu: {
        index: 0,
        tag: {},
        menuLeft: 0,
        isShow: false
      }
    };
  },
  watch: {
    $route() {
      this.getThisPage();
    },
    tags() {
      this.listenFun(this.$refs.tags, "tags");
    }
  },
  mounted() {
    this.listenFun(this.$refs.box, "box");
    var that = this;
    document.addEventListener("click", function(e) {
      that.contextMenu.isShow = false;
    });
  },
  methods: {
    // 監(jiān)聽可視區(qū)域?qū)?瀏覽器窗口大小改變執(zhí)行
    listenFun(monitor, dom) {
      let boxWidth = this.$refs.box.offsetWidth,
        tagsWidth = this.$refs.tags.offsetWidth,
        erd = elementResizeDetectorMaker();
      erd.listenTo(monitor, ele => {
        this.$nextTick(() => {
          if (
            (dom == "box" && ele.offsetWidth >= tagsWidth) ||
            (dom == "tags" && ele.offsetWidth <= boxWidth)
          ) {
            this.arrowVisible = false;
            this.$refs.box.style.paddingLeft = "16px";
            this.$refs.box.style.paddingRight = "16px";
            this.$refs.box.style.transform = "TranslateX(0px)";
            this.num = 0;
          } else {
            this.arrowVisible = true;
            this.$refs.box.style.paddingLeft = "56px";
            this.$refs.box.style.paddingRight = "56px";
          }
        });
      });
    },
    // 判斷當(dāng)前頁(yè)
    getThisPage() {
      let currentPgae = this.$route;
      // 判斷tags里是否有當(dāng)前頁(yè)面
      var index = this.tags.findIndex(tag => tag.name == currentPgae.name);
      if (index == -1) {
        this.tags.push({
          name: currentPgae.name,
          path: currentPgae.path
        });
      }
      // 當(dāng)前選擇頁(yè)
      this.active = this.tags.findIndex(tag => tag.name == currentPgae.name);
    },
    // 關(guān)閉標(biāo)簽
    handleClose(index, tag) {
      this.tags.splice(this.tags.indexOf(tag), 1);
      if (index == this.tags.length) {
        this.active = index - 1;
        this.$router.push(this.tags[index - 1].path);
      } else {
        this.$router.push(this.tags[index].path);
      }
    },
    // 點(diǎn)擊標(biāo)簽
    clickTag(index, tag) {
      this.active = index;
      this.$router.push(tag.path);
    },
    // 左側(cè)按鈕
    handleClickToLeft() {
      if (this.num > 0) {
        this.num--;
        this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
      }
    },
    // 右側(cè)按鈕
    handleClickToRight() {
      // 最后一個(gè)標(biāo)簽右測(cè)距離瀏覽器左側(cè)距離
      let lastChild = document
        .querySelectorAll(".top_tags")
        [this.tags.length - 1].getBoundingClientRect().right;
      // 可視窗口的寬
      let bodyWidth = document.body.offsetWidth;
      // 右側(cè)箭頭48+右側(cè)邊距16
      if (bodyWidth - lastChild <= 64) {
        this.num++;
        this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
      }
    },
    // 右鍵
    handleClickContextMenu(index, tag) {
      this.contextMenu.isShow = true;
      this.contextMenu.index = index;
      this.contextMenu.tag = tag;
      let isTag = document
        .querySelectorAll(".top_tags")
        [index].getBoundingClientRect();
      this.contextMenu.menuLeft = isTag.left - 48 + isTag.width / 2 + "px";
    },
    // 刷新
    refresh() {
      this.$router.go(0);
    },
    // 關(guān)閉其他
    closeOtherTag() {
      let tagsLin = this.tags.length,
        { index, tag, menuLeft } = this.contextMenu;
      if (index != 0) {
        this.tags = [
          {
            name: "Firstpage1",
            path: "/First/page1"
          },
          {
            name: tag.name,
            path: tag.path
          }
        ];
      } else {
        this.tags = [
          {
            name: "Firstpage1",
            path: "/First/page1"
          }
        ];
      }
      this.active = index;
      this.$router.push(tag.path);
    },
    // 關(guān)閉右側(cè)
    closeRightTag() {
      let tagsLin = this.tags.length,
        { index, tag, menuLeft } = this.contextMenu;
      this.tags.splice(index + 1, tagsLin - index);
      this.active = index;
      this.$router.push(tag.path);
    }
  },
  created() {
    // 監(jiān)聽頁(yè)面刷新
    window.addEventListener("beforeunload", e => {
      localStorage.setItem(
        "tagInfo",
        JSON.stringify({
          active: this.active,
          tags: this.tags
        })
      );
    });
    let tagInfo = localStorage.getItem("tagInfo")
      ? JSON.parse(localStorage.getItem("tagInfo"))
      : {
          active: 0,
          tags: [
            {
              name: "Firstpage1",
              path: "/First/page1"
            }
          ]
        };
    this.active = tagInfo.active;
    this.tags = tagInfo.tags;
  }
};
</script>
<style lang="less" scoped>
/deep/.el-tag--dark {
  border-color: transparent;
}
/deep/.el-tag--dark .el-tag__close {
  color: #86909c;
  font-size: 16px;
}
/deep/.el-tag--dark .el-tag__close:hover {
  background: #e7eaf0;
}
.tags {
  position: relative;
  overflow: hidden;
  .arrow {
    width: 48px;
    text-align: center;
    cursor: pointer;
    background: #fff;
    position: absolute;
    z-index: 1;
    &_left {
      left: 0;
      top: 0;
    }
    &_right {
      right: 0;
      top: 0;
    }
  }
  &_content {
    transition: 0.3s;
    white-space: nowrap;
    // padding: 0 16px;
  }
  .top_tags {
    margin-right: 8px;
    cursor: pointer;
    background: #fff;
    font-size: 12px;
    font-weight: 400;
    color: #1d2129;
  }
  .top_tags:hover,
  .active,
  .arrow:hover {
    background: #e7eaf0;
  }
}
</style>

重點(diǎn)

需要修改的地方

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

currentPgae.name 是路由結(jié)構(gòu)的name,判斷有無(wú)存在,沒有就添加,有就定位到上面,根據(jù)項(xiàng)目修改

Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史

監(jiān)聽刷新時(shí),去本地存儲(chǔ) tags 和 當(dāng)前頁(yè)面的active,F(xiàn)tistpage1 改成自己的首頁(yè)即可 

以上是“Vue如何實(shí)現(xiàn)頂部tags瀏覽歷史”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI