实现一个面包屑导航组件。面包屑导航用于显示当前页面的路径,并提供快速跳转到上级页面的功能,且可以通过右击菜单的命令实现关闭其他、关闭左侧和关闭右侧的功能
<template>
<div
class="breadcrumbWrapper"
ref="breadcrumbWrapper"
@contextmenu.prevent="showClickAllBtn"
@click="handlePopClose"
>
<el-breadcrumb class="app-levelbar" ref="appLevelbar">
<el-breadcrumb-item
v-for="(item, index) in levelList"
:key="item.path"
:class="activeIndex === index ? 'activeClass' : ''"
ref="breadcrumbItem"
>
<router-link :to="item.path" @click.native.stop="handleClick(index)">{{
item.name
}}</router-link>
<template>
<i
class="el-icon-close closeBtn"
@click.stop="handleDeleteClick(index)"
v-if="isShowClose"
></i>
</template>
</el-breadcrumb-item>
</el-breadcrumb>
<div class="clickRightClose">
<div class="closeBtn" @click="closeCurrent">关闭当前 </div>
<div class="closeBtn" @click="closeOther">
关闭其他
</div>
<div class="closeBtn" @click="closeRight">
关闭右侧
</div>
<div class="closeBtn" @click="closeLeft">
关闭左侧
</div>
</div>
</div>
</template>
<script>
import BScroll from "better-scroll";
export default {
created() {
this.getBreadcrumb();
},
data() {
return {
levelList: [],
flag: false,
activeIndex: 0,
isShowClose: true,
rightClickTab: "",
rightClickTabIndex: ""
};
},
methods: {
getBreadcrumb() {
let title = this.$route.meta.title;
let path = this.$route.path;
let params = this.$route.params;
let flag = this.levelList.find(item => {
return item.name === title;
});
this.flag = !flag;
// 路由跳转,添加到面包屑中
if (this.flag && title !== undefined) {
this.levelList.push({
name: title,
path: path,
params: params
});
}
this.levelList.forEach((v, i) => {
if (v.name === title) {
this.activeIndex = i;
}
});
},
handleClick(i) {
let isMenuOpen = this.$route.meta.menuPath.length <= 1 ? true : false;
let breadCrumbActiveIndex = "";
if (Object.keys(this.$route.params).length > 0) {
let params = this.$route.params;
let fullPath = this.$route.fullPath;
let strArr = fullPath.split("/");
strArr.pop();
strArr.shift();
let newStr = strArr.join("/");
let strParams = "";
// eslint-disable-next-line guard-for-in
for (let key in params) {
strParams = `${key}=${params[key]}`;
}
breadCrumbActiveIndex = `${newStr}?${strParams}`;
} else {
breadCrumbActiveIndex = this.$route.fullPath.slice(1);
}
// 用于选中菜单
this.$store.commit("setbreadCrumbActiveIndex", breadCrumbActiveIndex);
// 用于菜单展开状态
this.$store.commit("setIsOpen", isMenuOpen);
this.activeIndex = i;
},
handleDeleteClick(i) {
if (i === 0 && this.activeIndex === 0) {
this.levelList.splice(i, 1);
this.activeIndex = 0;
this.$router.push(this.levelList[0].path);
} else if (i !== this.levelList.length - 1) {
this.levelList.splice(i, 1);
this.activeIndex--;
this.$router.push(this.levelList[this.activeIndex].path);
} else {
this.levelList.splice(i, 1);
this.$router.push(this.levelList[this.levelList.length - 1].path);
}
},
getWidth() {
this.$nextTick(() => {
let allWidth = 0;
let nodes = document.querySelectorAll(".el-breadcrumb__item");
let appLevelbar = document.querySelector(".app-levelbar");
let breadcrumbWrapper = document.querySelector(".breadcrumbWrapper");
let breadcrumbWrapperWidth = parseFloat(
window.getComputedStyle(breadcrumbWrapper, null)["width"]
);
nodes.forEach(v => {
let w = parseFloat(window.getComputedStyle(v, null)["width"]);
let r = parseFloat(window.getComputedStyle(v, null)["marginRight"]);
let l = parseFloat(window.getComputedStyle(v, null)["marginLeft"]);
allWidth += w + r + l;
});
appLevelbar.style.width = allWidth + "px";
if (allWidth > breadcrumbWrapperWidth) {
this.scroll = new BScroll(this.$refs.breadcrumbWrapper, {
scrollX: true
});
let activeDom = document.querySelector(
".el-breadcrumb__item.activeClass"
);
this.scroll.scrollToElement(activeDom, 0, 0);
this.scroll.refresh();
}
});
},
showClickAllBtn(e) {
if (this.levelList.length > 1 && e.path[0].nodeName !== "DIV") {
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "block";
closeBtn.style.left = e.clientX + "px";
closeBtn.style.top = 110 + "px";
this.rightClickTab = e.path[0].innerText;
this.rightClickTabIndex = this.getRightClickTabIndex(
this.rightClickTab
);
}
},
getRightClickTabIndex(arg) {
let tabList = [];
this.levelList &&
this.levelList.forEach(v => {
tabList.push(v.name);
});
let rightClickTabIndex = tabList.indexOf(arg);
return rightClickTabIndex;
},
// 左击关闭弹框
handlePopClose() {
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
},
// 关闭当前
closeCurrent() {
this.levelList.splice(this.rightClickTabIndex, 1);
this.activeIndex =
this.rightClickTabIndex > 0 ? this.rightClickTabIndex - 1 : 0;
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
this.$router.push(this.levelList[this.activeIndex].path);
this.getWidth();
},
// 关闭其他
closeOther() {
this.levelList = this.levelList.splice(this.rightClickTabIndex, 1);
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
this.activeIndex = 0;
this.$router.push(this.levelList[0].path);
this.getWidth();
},
// 关闭全部
closeAll() {
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
this.levelList.splice(1);
this.activeIndex = 0;
this.$router.push(this.levelList[0].path);
this.getWidth();
},
// 关闭右侧
closeRight() {
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
this.levelList.splice(
this.rightClickTabIndex + 1,
this.levelList.length - 1
);
this.activeIndex = this.rightClickTabIndex;
this.$router.push(this.levelList[this.activeIndex].path);
this.getWidth();
},
// 关闭左侧
closeLeft() {
let closeBtn = document.querySelector(".clickRightClose");
closeBtn.style.display = "none";
this.levelList.splice(0, this.rightClickTabIndex);
this.activeIndex = this.levelList.length - 1;
this.$router.push(this.levelList[this.activeIndex].path);
this.getWidth();
}
},
watch: {
$route() {
this.getWidth();
this.getBreadcrumb();
},
levelList: {
handler(val) {
// this.getWidth();
if (val.length > 1) {
this.isShowClose = true;
} else {
this.isShowClose = false;
}
}
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.breadcrumbWrapper {
width: 100%;
border-top: 1px solid #cfdfe6;
overflow: hidden;
box-sizing: border-box;
height: 50px;
.app-levelbar {
white-space: nowrap;
width: 2000px;
}
.clickRightClose {
position: fixed;
display: none;
// border: 1px solid #ccc;
// padding: 5px;
font-size: 14px;
z-index: 1000;
color: #333;
background: #fff;
cursor: pointer;
.closeBtn {
padding: 10px 25px;
&:hover {
background: #d7eff3;
}
}
}
}
.el-breadcrumb {
line-height: 50px;
box-sizing: border-box;
height: 50px;
/deep/ .el-breadcrumb__item {
cursor: pointer;
margin-right: 30px;
display: inline-block;
float: none;
box-sizing: border-box;
height: 46px;
.el-breadcrumb__inner {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
a {
display: inline-block;
padding-left: 10px;
color: #666;
cursor: pointer;
font-size: 16px;
font-weight: 400;
&:hover {
color: #666;
font-size: 16px;
font-weight: 400;
}
}
.closeBtn {
font-size: 16px;
padding-left: 20px;
color: #bbb;
cursor: pointer;
}
}
.el-breadcrumb__separator {
display: none;
}
&.activeClass {
color: #069dbc;
border-bottom: 2px solid #069dbc;
.el-breadcrumb__inner {
a {
color: #069dbc;
}
.closeBtn {
color: #069dbc;
}
}
}
}
}
</style>