效果图如下:
当标签栏很多的时候效果图如下:
左侧菜单布局 ($route.path高亮显示激活路由 :default-active="$route.path"
)
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo"
background-color="#323744"
text-color="#fff"
active-text-color="#409eff"
:collapse="iscollapse"
unique-opened
:collapse-transition="false"
router
>
<template v-for="(item, index) in menuList">
<!-- 有下拉 -->
<el-submenu v-if="item.children" :index="item.id" :key="index">
<template slot="title">
<svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
<span>{{ item.title }}</span>
</template>
<el-menu-item-group
v-for="(item, index) in item.children"
:key="index"
>
<el-menu-item :index="item.path" @click="clickMenu(item)">
<template slot="title">
<svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
<span>{{ item.subtitle1 }}</span>
</template>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<!-- 没有下拉 -->
<el-menu-item v-else :key="index" :index="item.path" @click="clickMenu(item)">
<svg-icon :className="item.icon" :iconClass="item.icon"></svg-icon>
<span slot="title">{{ item.subtitle1 }}</span>
</el-menu-item>
</template>
</el-menu>
模拟数据如下:(以下路径均需在router/index.js里面进行配置)
menuList: [
{
id: "9",
subtitle1: "首页",
icon: "shangjiadianpu",
path: "/welcome",
},
{
id: "1",
title: "用户管理",
icon: "huangguanyonghu",
children: [
{
id: "1-1",
subtitle1: "时间-moment",
icon: "huangguanyonghu",
path: "/user",
},
{
id: "1-2",
subtitle1: "删除用户",
icon: "huangguanyonghu",
img: require("@/assets/logo.png"),
path: "/user2",
},
{
id: "1-3",
subtitle1: "图片放大",
icon: "huangguanyonghu",
path: "/user3",
},
],
},
{
id: "2",
title: "表格",
icon: "ershoujiaoyi",
children: [
{
id: "2-1",
subtitle1: "表格排序",
icon: "ershoujiaoyi",
path: "/tableSort",
},
{
id: "2-2",
subtitle1: "动画",
icon: "ershoujiaoyi",
path: "/animation",
},
{
id: "2-3",
subtitle1: "权限3",
icon: "ershoujiaoyi",
path: "/limit3",
},
],
},
{
id: "6",
subtitle1: "拖拽-sortablejs",
icon: "shangpuchuzu",
path: "/sortable",
},
{
id: "7",
title: "功能",
icon: "ershoujiaoyi",
children: [
{
id: "7-1",
subtitle1: "上下滚动",
icon: "ershoujiaoyi",
path: "/numscroll",
},
{
id: "7-9",
subtitle1: "数字滚动",
icon: "ershoujiaoyi",
path: "/icountup",
},
{
id: "7-2",
subtitle1: "动画",
icon: "ershoujiaoyi",
path: "/animation",
},
{
id: "7-3",
subtitle1: "调用摄像头",
icon: "ershoujiaoyi",
path: "/opencamera",
},
{
id: "7-4",
subtitle1: "裁剪图片",
icon: "ershoujiaoyi",
path: "/cropperjs",
},
{
id: "7-5",
subtitle1: "裁剪图片2",
icon: "ershoujiaoyi",
path: "/vuecropper",
},
{
id: "7-6",
subtitle1: "打印功能",
icon: "ershoujiaoyi",
path: "/printjs",
},
{
id: "7-7",
subtitle1: "vue-pfd预览",
icon: "ershoujiaoyi",
path: "/vuepdf",
},
{
id: "7-8",
subtitle1: "内嵌iframe",
icon: "ershoujiaoyi",
path: "/iframepdf",
},
{
id: "7-10",
subtitle1: "放大镜功能",
icon: "ershoujiaoyi",
path: "/magnifier",
},
{
id: "7-11",
subtitle1: "多表头表格",
icon: "ershoujiaoyi",
path: "/xlsx",
},
{
id: "7-12",
subtitle1: "单表头表格",
icon: "ershoujiaoyi",
path: "/xlsx2",
},
{
id: "7-13",
subtitle1: "Vuecontextmenu",
icon: "ershoujiaoyi",
path: "/vuecontextmenu",
},
{
id: "7-14",
subtitle1: "vcontextmenu",
icon: "ershoujiaoyi",
path: "/vcontextmenu",
},
{
id: "7-15",
subtitle1: "表格合并",
icon: "ershoujiaoyi",
path: "/tablehebing",
},
{
id: "7-16",
subtitle1: "日期选择",
icon: "ershoujiaoyi",
path: "/datepicker",
},
{
id: "7-17",
subtitle1: "treeselect",
icon: "ershoujiaoyi",
path: "/treeselect",
},
{
id: "7-19",
subtitle1: "大屏数据",
icon: "ershoujiaoyi",
path: "/datav",
},
{
id: "7-20",
subtitle1: "左右菜单联动",
icon: "ershoujiaoyi",
path:'/leftrightmenu'
},
{
id: "7-18",
subtitle1: "测试页面",
icon: "ershoujiaoyi",
path: "/test",
},
],
},
],
主要内容区域标签栏布局如下:
<el-tabs
class="vab-tabs-content"
v-model="activeIndex"
type="card"
@tab-click="clickTab"
@tab-remove="removeTab"
>
<el-tab-pane
v-for="item of openTab"
v-if="openTab.length"
:key="item.name"
:label="item.name"
:name="item.route"
:closable="isNoClosable(item)"
>
</el-tab-pane>
</el-tabs>
标签栏样式
/deep/.el-tabs__header .el-tabs__nav{
border:none;
}
/deep/.el-tabs--card>.el-tabs__header{
border:none;
}
/deep/.el-tabs__header .el-tabs__item{
padding:0 30px;
border:none
}
/deep/.el-tabs__header .el-tabs__item.is-active {
color: #1890ff;
background: #e8f4ff;
outline: none;
-webkit-mask: url(~@/assets/images/tabs-bg.png);
mask: url(~@/assets/images/tabs-bg.png);
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
/deep/.el-tabs__header .el-tabs__item:hover {
color: #515a6e;
background: #dee1e6;
-webkit-mask: url(~@/assets/images/tabs-bg.png);
mask: url(~@/assets/images/tabs-bg.png);
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
/deep/.el-tabs--card > .el-tabs__header .el-tabs__item.is-closable:hover {
padding-left: 30px;
padding-right: 30px;
}
/deep/.el-tabs__header .el-tabs__item.is-active.is-closable {
padding-left: 30px;
padding-right: 30px;
}
/deep/.el-tabs__header .el-tabs__item.is-active:hover {
color: #1890ff !important;
background: #e8f4ff !important;
// padding: 0 30px 0 30px;
}
.el-tabs__header .el-tabs__item.is-active:hover {
color: #1890ff;
background: #e8f4ff;
-webkit-mask: url(~@/assets/images/tabs-bg.png);
mask: url(~@/assets/images/tabs-bg.png);
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
创建一个仓库模块 @/store/Modules/tabs.js
tabs.js代码如下
export default{
namespaced: true, //开启命名空间
state: {
openTab: JSON.parse(sessionStorage.getItem('openTab'))|| [],
activeIndex: ''
},
mutations: {
add_tabs (state, data) {
//如果等于-1说明tabs不存在那么插入,否则什么都不做
//findindex找角标,循环判断一下,如果等于那么就代表有相同的,就不必添加,如果找不到那就是-1.就添加
let result = state.openTab.findIndex(item => item.name === data.name);
result === -1 ? state.openTab.push(data) : '';
// 存到本地 页面刷新不丢失
sessionStorage.setItem('openTab',JSON.stringify(state.openTab))
},
delete_tabs (state, route) {
let index = 0
for (let gohh of state.openTab) {
if (gohh.route === route) {
break
}
index++
}
state.openTab.splice(index, 1)
// 存到本地 页面刷新不丢失
sessionStorage.setItem('openTab',JSON.stringify(state.openTab))
},
set_active_index (state, index) {
console.log(index);
state.activeIndex = index
}
}
}
将tab.js模块引入@store/index.js
import Vue from 'vue'
import Vuex from 'vuex
import tabs from './Modules/tabs'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
tabs
}
})
主要逻辑代码如下:
在主要内容区域引入如下代码获取tabs.js仓库里面的值在页面进行渲染
computed: {
openTab () {
return this.$store.state.tabs.openTab
},
activeIndex: {
get () {
return this.$store.state.tabs.activeIndex
},
set (val) {
this.$store.commit('tabs/set_active_index', val)
}
}
},
给左侧菜单导航绑定点击事件clickMenu,去触发仓库的add_tabs事件,把数组添加到openTab数组里面(添加前需要判断openTab是否有当前值,有就不添加,反之添加),把activeIndex也改变
clickMenu(val){
//备注 :分模块触发事件可参考vue官网 '模块名/事件名'
this.$store.commit('tabs/add_tabs',{route: val.path , name: val.subtitle1 })
this.$store.commit('tabs/set_active_index', val.path)
},
给标签绑定点击事件clickTab 跳转到对应路由,给标签叉叉绑定removeTab (tab-remove 点击 tab 移除按钮后触发 被删除的标签的 name)拿到对应的路由进行判断
1、如果是首页则不删除;
2、如果删除的高亮激活这一项,则跳转到最后openTab数组的最后一项并高亮;
3、如果删除的不是高亮激活这一项,则不跳转,高亮激活项不变。
clickTab (tab) {
console.log(tab);
this.$router.push({path: this.activeIndex})
},
removeTab (target) {
if(target == '/'||target == '/welcome'){
return
}
this.$store.commit('tabs/delete_tabs', target)
if (this.activeIndex === target) {
// 设置当前激活的路由
if (this.openTab && this.openTab.length >= 1) {
console.log('=============', this.openTab[this.openTab.length - 1].route)
this.$store.commit('tabs/set_active_index', this.openTab[this.openTab.length - 1].route)
this.$router.push({path: this.activeIndex})
}
}
},
给el-tab-pane标签绑定属性 :closable="isNoClosable(item)
判断el-tab-pane是否显示叉叉,除了首页不显示,其他均显示
isNoClosable(item){
return item.route !== '/welcome'
},
刷新时以当前路由做为tab加入tabs,当前路由不是首页时,添加首页以及另一页到store里,并设置激活状态,当前路由是首页时,添加首页到store,并设置激活状态(注意:this.$route.meta.title的title值要和菜单数据里面的subtitle1名称保持一致!!!)
mounted () {
console.log(this.$route);
// 刷新时以当前路由做为tab加入tabs
// 当前路由不是首页时,添加首页以及另一页面到store里,并设置激活状态
// 当前路由是首页时,添加首页到store,并设置激活状态
if (this.$route.path !== '/welcome') {
this.$store.commit('tabs/add_tabs', {route: '/welcome' , name: '首页'})
this.$store.commit('tabs/add_tabs', {route: this.$route.path , name: this.$route.meta.title })
this.$store.commit('tabs/set_active_index', this.$route.path)
} else {
this.$store.commit('tabs/add_tabs', {route: '/welcome', name: '首页'})
this.$store.commit('tabs/set_active_index', '/welcome')
}
}
实现思路大致就是这样,主要自己项目的数据稍作修改。