Vue頂部tags瀏覽歷史的實現
廢話
demo預覽
實現的功能
默認有首頁,不能關閉
點擊路由菜單,判斷有無存在,沒有就添加,有就定位到上面
點擊跳轉,點擊X可關閉
關閉當前頁,自動跳到下一個tag頁面
如果當前頁在最後一個,默認跳到上一個tag頁面
右鍵菜單,刷新,關閉右側,關閉所有
動態判斷tags長多,放不下時,出現左右兩側按鈕,減少時自動消失
動態判斷窗口放大縮小,自動判斷有無左右兩側按鈕
正文
不用任何vuex,亂七八糟的方法,全在一個文件,粘貼即用
放到你想要的位置即可(此demo,放在瞭面包屑上面)
先安裝 (監聽某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> <!-- 標簽內容 --> <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" :style="{ left: contextMenu.menuLeft, top: '96px' }" 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"> 關閉右側 </li> <li class="el-dropdown-menu__item" @click="closeOtherTag"> 關閉其它 </li> <div x-arrow="" class="popper__arrow" style="left: 44px;"></div> </ul> </div> </template> <script> import elementResizeDetectorMaker from "element-resize-detector"; export default { data() { return { // 是否有箭頭 arrowVisible: true, // 點擊次數 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: { // 監聽可視區域寬,瀏覽器窗口大小改變執行 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"; } }); }); }, // 判斷當前頁 getThisPage() { let currentPgae = this.$route; // 判斷tags裡是否有當前頁面 var index = this.tags.findIndex(tag => tag.name == currentPgae.name); if (index == -1) { this.tags.push({ name: currentPgae.name, path: currentPgae.path }); } // 當前選擇頁 this.active = this.tags.findIndex(tag => tag.name == currentPgae.name); }, // 關閉標簽 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); } }, // 點擊標簽 clickTag(index, tag) { this.active = index; this.$router.push(tag.path); }, // 左側按鈕 handleClickToLeft() { if (this.num > 0) { this.num--; this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`; } }, // 右側按鈕 handleClickToRight() { // 最後一個標簽右測距離瀏覽器左側距離 let lastChild = document .querySelectorAll(".top_tags") [this.tags.length - 1].getBoundingClientRect().right; // 可視窗口的寬 let bodyWidth = document.body.offsetWidth; // 右側箭頭48+右側邊距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); }, // 關閉其他 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); }, // 關閉右側 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() { // 監聽頁面刷新 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>
重點
需要修改的地方
currentPgae.name 是路由結構的name,判斷有無存在,沒有就添加,有就定位到上面,根據項目修改
監聽刷新時,去本地存儲 tags 和 當前頁面的active,Ftistpage1 改成自己的首頁即可
到此這篇關於Vue頂部tags瀏覽歷史的實現的文章就介紹到這瞭,更多相關Vue頂部tags瀏覽歷史內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- vue router-view的嵌套顯示實現
- ElementUI中的el-dropdown傳入多參數的實現方法
- Vue實現路由嵌套的方法實例
- vue+elementui+vuex+sessionStorage實現歷史標簽菜單的示例代碼
- elementUI組件el-dropdown(踩坑)