Vue顶部tags浏览历史
郭顺杰 人气:0废话
实现的功能
默认有首页,不能关闭
点击路由菜单,判断有无存在,没有就添加,有就定位到上面
点击跳转,点击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 改成自己的首页即可
加载全部内容