目录
废话
实现的功能
默认有首页,不能关闭
点击路由菜单,判断有无存在,没有就添加,有就定位到上面
点击跳转,点击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 改成自己的首页即可
© 版权声明
THE END
暂无评论内容