# 两种导航实现方式
# 1.定位方式显示
效果
@ 系统管理>用户管理>新增用户
<el-main class="main-container">
<!-- 导航 -->
<div class="nav-icon">
<i class="el-icon-location-information" />
</div>
<div class="breadcrunb-box">
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item v-for="(itme, index) in breadcrumb" :key="index">{{ itme }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<app-main class="app-main" />
</el-main>
<script>
import { Navbar, Sidebar, AppMain, Footer } from './components'
import { mapGetters } from 'vuex'
export default {
name: 'Layout',
components: { Navbar, Sidebar, AppMain, 'footer-component': Footer },
data() {
return {
breadcrumb: ['首页']
}
},
computed: {
...mapGetters(['menu_tree', 'user_info'])
},
watch: {
$route(v) {
this.setBreadcrumb(this.menu_tree, v.path)
}
},
mounted() {
const menuTree = this.$store.getters.menu_tree
const uri = this.$route.path
this.setBreadcrumb(menuTree, uri)
},
methods: {
setBreadcrumb(tree, uri) {
const breadcrumb_copy = [...this.breadcrumb]
this.breadcrumb = []
if (uri === '/' || uri === '/home') {
this.breadcrumb.push('首页')
return
}
try {
this.getTreeNode(tree, uri)
} catch (e) { return }
if (this.breadcrumb.length === 0) {
this.breadcrumb = breadcrumb_copy
}
},
getTreeNode(tree, uri) {
tree.forEach(element => {
this.breadcrumb.push(element.name)
if (uri === element.uri) {
throw element
}
const children = element.children
if (children && children.length > 0) {
this.getTreeNode(children, uri)
}
this.breadcrumb.pop()
})
}
}
}
</script>
# 2.tab切换方式显示(带有组件缓存)
要求
- 1.路由表深度最多两级
- 2.AppMain.vue 开启 keep-alive
- 3.规范每一个 views 组件 name 的值 且唯一 xxxxPage
<template>
<div class="app-main">
<el-scrollbar wrap-class="scrollbar-wrapper scrollbar-wrapper-min-width">
<transition name="fade" mode="out-in">
<keep-alive :include="keep_alives">
<router-view :key="key" />
</keep-alive>
</transition>
</el-scrollbar>
</div>
</template>
<template>
<div class="tags-view">
<div class="div-tabs">
<el-tabs
v-model="tabValue"
type="card"
closable
@tab-click="handleTabsClick"
@tab-remove="handleCloseClick"
>
<el-tab-pane v-for="item in tabs" :key="item.path" :label="item.name" :name="item.path" />
</el-tabs>
</div>
<el-dropdown v-show="tabs.length > 1" class="dropdown-close" @command="batchCloseTabs">
<span class="el-dropdown-link">
<i class="el-icon-s-fold btn-close" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="now">关闭当前</el-dropdown-item>
<el-dropdown-item v-show="tabs.length > 2" command="other">关闭其他</el-dropdown-item>
<el-dropdown-item v-show="tabs.length > 2" command="all">关闭所有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'TabsView',
data() {
return {
tabValue: '',
defTabItem: {
name: '首页',
path: '/home'
},
tabs: []
}
},
computed: {
...mapGetters(['menu_list'])
},
watch: {
$route(v) {
const isExits = this.isExits(v.path)
if (isExits) {
this.tabValue = v.path
} else {
this.addTabs(v)
this.addKeepAlives(v)
}
}
},
mounted() {
const { name, path } = this.$route
const route = { name, path }
// 设置初始值
this.tabs.push(this.defTabItem)
this.tabValue = route.path
const isHave = this.tabs.find(item => {
return item.path === route.path
})
console.log(this.$route)
if (!isHave) {
// 直接访问路径的时候
this.tabs.push(route)
}
},
destroyed() {
this.tabs.forEach(item => {
this.removeKeepAlives(item.path)
})
},
methods: {
handleTabsClick(tab) {
this.$router.push(tab.name)
},
handleCloseClick(targetPath) {
const len = this.tabs.length
const defTabItemPath = this.defTabItem.path
if (targetPath === defTabItemPath) return // 保留首页
for (var i = 0; i < len; i++) {
if (this.tabs[i].path === targetPath) {
var nextTab = this.tabs[i + 1] || this.tabs[i - 1]
if (nextTab) {
this.tabValue = nextTab.path
}
}
}
this.tabs = this.tabs.filter(tab => tab.path !== targetPath)
this.removeKeepAlives(targetPath)
this.$router.push(nextTab.path)
},
addTabs({ name, path, meta }) {
const defTabItemPath = this.defTabItem.path
// 不新开tab
if (meta.isTab !== undefined && !meta.isTab) return
if (path === defTabItemPath) return
const menu = this.menu_list.find(item => {
return item.uri === path
})
// 刷新的时候,调用菜单接口, 所以 vuex 可能没有值
if (menu) {
name = menu.name
}
this.tabs.push({ name, path })
this.tabValue = path
},
addKeepAlives({ path, meta, matched }) {
// 不缓存
if (meta.keepAlive !== undefined && !meta.keepAlive) {
return
}
const targetItem = matched.find(item => {
return item.path === path
})
const componentName = targetItem.components.default.name
if (componentName) {
this.$store.commit('menu/PUSH_KEEP_ALIVE', { key: path, value: componentName })
}
},
removeKeepAlives(path) {
this.$store.commit('menu/RMEOVE_KEEP_ALIVE', path)
},
batchCloseTabs: function (command) {
switch (command) {
case 'now':
this.handleCloseClick(this.tabValue)
break
case 'other':
this.removeOtherTabs()
break
case 'all':
this.homeTab()
break
default:
break
}
},
removeOtherTabs: function () {
this.tabs.forEach(item => {
const path = item.path
if (this.tabValue !== item.path) {
this.removeKeepAlives(path)
}
})
this.tabs = this.tabs
.filter(tab => tab.path === this.tabValue | tab.path === this.defTabItem.path)
},
homeTab: function () {
const defTabItemPath = this.defTabItem.path
this.tabs.forEach(item => {
this.removeKeepAlives(item.path)
})
this.tabs.length = 0
this.tabs.push(this.defTabItem)
this.tabValue = this.defTabItem.path
this.$router.push(defTabItemPath)
},
isExits: function (path) {
var len = this.tabs.length
for (var i = 0; i < len; ++i) {
if (this.tabs[i].path === path) return true
}
return false
}
}
}
</script>
<style scoped>
.tags-view >>> .el-icon-arrow-down:before {
color: #5c8df1;
}
.tags-view >>> .el-tabs__item {
height: 33px;
line-height: 33px;
font-size: 13px;
border-color: ivory;
border-top-left-radius: 7px;
border-top-right-radius: 7px;
}
.tags-view >>> .el-tabs__nav-prev {
border-top-left-radius: 7px;
background-color: rgba(160, 225, 251, 0.98);
line-height: 38px;
font-size: 16px;
z-index: 3;
}
.tags-view >>> .el-tabs__nav-next {
border-top-right-radius: 7px;
background-color: rgba(160, 225, 251, 0.98);
line-height: 38px;
font-size: 16px;
z-index: 3;
}
.tags-view >>> .el-tabs__nav-wrap.is-scrollable {
padding: 0;
}
.tags-view >>> .el-tabs--card > .el-tabs__header .el-tabs__item.is-active {
border-bottom-color: rgba(240, 255, 255, 0.6);
}
.tags-view >>> .el-tabs__item.is-active {
color: #1890ff;
background-color: rgba(240, 255, 255, 0.6);
}
</style>
<style lang="scss" scoped>
.tags-view {
height: 35px;
border-top-right-radius: inherit;
padding: 1px 0 0 1px;
border-bottom: 1px solid #dfe4ed;
background-color: rgba(64, 184, 255, 0.2);
.div-tabs {
position: absolute;
float: left;
width: calc(100vw - 300px);
}
.dropdown-close {
cursor: pointer;
float: right;
}
.btn-close {
font-size: 21px;
height: 20px;
margin: 7px 2px;
color: #5cb6f1;
}
}
</style>