Vue+vuex+vue-router+element-ui实现侧边栏和可增删的标签页(附源码)
运行结果参考博客:https://blog.csdn.net/weixin_43930186/article/details/86677941存在缺陷:你点击标签页的时候路由里面颜色没有跳转,因为时间问题就没有深究了。后面如果还能再碰到就会去解决一下1.安装相应的依赖可以参考我的这篇博客:https://blog.csdn.net/weixin_45969142/article/details/1
·
运行结果
参考博客:https://blog.csdn.net/weixin_43930186/article/details/86677941
存在缺陷:你点击标签页的时候路由里面颜色没有跳转,因为时间问题就没有深究了。后面如果还能再碰到就会去解决一下
1.安装相应的依赖
可以参考我的这篇博客:https://blog.csdn.net/weixin_45969142/article/details/114126518
2.工程目录结构
3.建立store文件夹,建立index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
id: '123456',
openedTab: ['首页','system'],
activeTab: ''
},
mutations: {
//将name参数加入到openedTab数组中
addNameTab(state, name){
state.openedTab.push(name)
},
//将componentName参数加入到openedTab数组中
addTab (state, componentName) {
// 传递参数
state.openedTab.push(componentName)
},
changeTab (state, componentName) {
state.activeTab = componentName
},
deductTab (state, componentName) {
let index = state.openedTab.indexOf(componentName)
let indextwo = index-1;
state.openedTab.splice(index, 1)
//删除一次后,数组减少一。所以删除一样的位置,就能删除前面的那个
state.openedTab.splice(indextwo, 1)
}
}
})
4.App.vue
<template>
<div id="app">
<el-container>
<el-header class="header">
<NavigationTop></NavigationTop>
</el-header>
<el-container>
<el-aside width="200px">
<NavigationLeft></NavigationLeft>
</el-aside>
<el-main>
<NavigationMainTab></NavigationMainTab>
<keep-alive>
<router-view/>
</keep-alive>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import NavigationLeft from '@/components/NavigationLeft/NavigationLeft'
import NavigationTop from '@/components/NavigationTop/NavigationTop'
import NavigationMainTab from '@/components/navMain/NavigationMainTab'
export default {
name: 'App',
components: {
NavigationLeft,
NavigationTop,
NavigationMainTab
}
}
</script>
<style>
.header{
background: #636363;
line-height: 60px;
}
</style>
5.router文件下的index.js文件
import Vue from 'vue';
import VueRouter from 'vue-router';
import userManage from "../views/userManage";
import HomePage from "../components/navMain/mainComponents/HomePage"
import businessManagement from '../components/navMain/mainComponents/businessManagement'
import adminManagement from '../components/navMain/mainComponents/adminManagement'
import userManagement from '../components/navMain/mainComponents/userManagement'
Vue.use(VueRouter);
const routes = [
{
path: '/system',
name: 'HomePage',
component: HomePage
},
{
path: '/businessManagement',
name: 'businessManagement',
component: businessManagement
},
{
path: '/adminManagement',
name: 'adminManagement',
component: adminManagement
},
{
path: '/userManagement',
name: 'userManagement',
component: userManagement
}
];
const router = new VueRouter({
routes,
// 去掉#号
mode: 'history'
});
export default router
6.导航栏的上部分NavgationTop.vue
<template>
<div id="header">
<span class="demonstration" style="float:left;padding-top:10px;color:white;">
RetalLife管理员后台系统
</span>
<span class="demonstration" style="float:left;padding:5px;color:white;margin-left:2%;width:15%">
<el-input
placeholder="请输入"
icon="search"
v-model="searchCriteria"
:on-icon-click="handleIconClick">
</el-input>
</span>
<span class="demonstration" style="float:right;padding-top:10px;margin-right:1%">
<el-dropdown trigger="click">
<span class="el-dropdown-link" style="color:white;margin-right: 0px">
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<i class="el-icon-caret-bottom el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人信息</el-dropdown-item>
<el-dropdown-item>退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</div>
</template>
<script>
export default {
name: 'navHeader'
}
</script>
<style scoped>
</style>
7.导航栏的左边部分NavigationLeft.vue
<!--本页为左侧下拉菜单-->
<template>
<div id="nav" style="margin-top: 0px">
<el-row class="tac">
<el-col :span="24">
<el-menu
default-active="1"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
unique-opened
router
active-text-color="#409EFF"
:collapse="isCollapse"
>
<el-menu-item index="1" >
<i :class="{'el-icon-s-fold': isCollapse == false?true:false, 'el-icon-s-unfold': isCollapse == true?true:false}" @click="isC"></i>
</el-menu-item>
<el-menu-item index="system" @click="clickMenu('system')">
<i class="el-icon-s-home"></i>
<span slot="title">首页</span>
</el-menu-item>
<el-submenu index="2">
<template slot="title">
<i class="el-icon-setting"></i>
<span>系统管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="userManagement" @click="clickMenu('userManagement','用户管理')">
<i class="el-icon-user"></i>
<span slot="title">用户管理</span>
</el-menu-item>
<el-menu-item index="adminManagement" @click="clickMenu('adminManagement','管理员管理')">
<i class="el-icon-admin"></i>
<span slot="title">管理员管理</span>
</el-menu-item>
<el-menu-item index="businessManagement" @click="clickMenu('businessManagement','厂商管理')">
<i class="el-icon-business"></i>
<span slot="title">厂商管理</span>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-menu-item index="4">
<i class="el-icon-s-comment"></i>
<span slot="title">聊天窗口</span>
</el-menu-item>
</el-menu>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'navMenu',
methods: {
isC() {
this.isCollapse = !this.isCollapse
},
clickMenu(componentName,name) {
this.openedTab = this.$store.state.openedTab
// tabNum 为当前点击的列表项在openedTab中的index,若不存在则为-1
let tabNum = this.openedTab.indexOf(componentName)
if (tabNum === -1) {
// 该标签当前没有打开
// 将name、componentName加入到已打开标签页state.openedTab数组中
this.$store.commit('addNameTab', name)
this.$store.commit('addTab', componentName)
} else {
// 该标签是已经打开过的,需要激活此标签页
this.$store.commit('changeTab', componentName)
}
}
},
data() {
return {
openedTab: [],
isCollapse: false
}
}
}
</script>
<style scoped>
.el-icon-user {
background: url('../../assets/yonghu.png') center center no-repeat;
background-size: 20px;
}
.el-icon-user:before {
content: "代替";
font-size: 16px;
visibility: hidden;
}
.el-icon-admin {
background: url('../../assets/guanliyuan.png') center center no-repeat;
background-size: 20px;
}
.el-icon-admin:before {
content: "代替";
font-size: 16px;
visibility: hidden;
}
.el-icon-business {
background: url('../../assets/changshang.png') center center no-repeat;
background-size: 20px;
}
.el-icon-business:before {
content: "代替";
font-size: 16px;
visibility: hidden;
}
</style>
8.导航栏的引起的标签页NavigationMainTab.Vue
<!--本页为tab标签-->
<template>
<el-tabs
v-model="editableTabsValue"
type="card"
closable
@tab-remove="removeTab"
@tab-click="handleClickTab($event.name)"
>
<el-tab-pane
:key="item.name"
v-for="item in editableTabs"
:label="item.title"
:name="item.name"
>
</el-tab-pane>
</el-tabs>
</template>
<script>
export default {
name: 'navMain',
data () {
return {
//做一个当时的状态网页
editableTabsValue: 'system',
editableTabs: [{
title: '首页',
name: 'system'
}],
//存储所有的路由网址
openedTab: ['system']
}
},
methods: {
//点击切换标签页
handleClickTab (route) {
this.$store.commit('changeTab', route)
//跳转该路由
this.$router.push(route)
},
//删除标签页
removeTab (targetName) {
// 首页不允许被关闭(为了防止el-tabs栏中一个tab都没有)
if (targetName === 'system') {
return false
}
//下面这一部分,可以观看el里面自动的增加标签页的代码
let tabs = this.editableTabs
let activeName = this.editableTabsValue
//editableTabsValue数组里面是否有与删除的标签页的路由相等
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1]
if (nextTab) {
activeName = nextTab.name
}
}
});
}
//删除标签页成功
this.$store.commit('deductTab', targetName)
//让openedTab,删除targetName这个下标对应的数据 openedTab存的是网址
let deductIndex = this.openedTab.indexOf(targetName)
this.openedTab.splice(deductIndex, 1)
this.editableTabsValue = activeName
//筛选出tabs中每一项的name值不等于targetName的项并返回一个新的数组举个栗子
// :arr=[1,2,3,4,5]arr.filter(i=>i!=1)//[2,3,4,5]更新:
// filter是已经封装好的方法,使用的时候只需要提供相应的参数就好了
//targetName===businessManagement !=== tab.name==editableTabs.name==英文构造
this.editableTabs = tabs.filter(tab =>tab.name !== targetName )
//跳转上一个标签,跳转成功
this.$router.push(activeName)
if (this.openedTab.length === 0) {
this.$store.commit('addTab', 'system')
this.$router.push('system')
}
}
},
computed: {
//computed与watch中的方法对应起来了,可以写一个getTitle的方法 明天就直接换一个方法吧,简单些。空想又想不出来
//得到openedTab数组里面的数据
getOpenedTab () {
return this.$store.state.openedTab
},
changeTab () {
return this.$store.state.activeTab
}
},
watch: {
getOpenedTab (val) {
//因为前面openedTab是个存路由网址的数组,所以需要this.openedTab.length*2
if (val.length > this.openedTab.length*2) {
// 添加了新的tab页
// 导致$store.state中的openedTab长度
// 大于
// 标签页中的openedTab长度
// 因此需要新增标签页
//componentName里面的值
let newTitle = val[val.length - 1] // 新增的肯定在数组最后一个
let newTab = val[val.length - 2]
this.editableTabs.push({
title: newTab,
name: newTitle,
content: ''
})
this.editableTabsValue = newTitle
this.openedTab.push(newTitle)
}
},
changeTab (val) {
// 监听activetab以实现点击左侧栏时激活已存在的标签
if (val !== this.editableTabsValue) {
this.editableTabsValue = val
}
}
},
created () {
// 刷新页面时(F11)
// 因为<router-view>的<keep-alive>,会保留刷新时所在的router
// 但是tab标签页因为刷新而被重构了,tab没有了
// 因此需要将router回到index
this.$router.push('system')
}
}
</script>
<style scoped>
</style>
9.标签页里面的内容为adminManagement.vue
<template>
<div>
<p>管理员管理</p>
</div>
</template>
<script>
export default {
name: 'BasicCheckbox'
}
</script>
<style scoped>
</style>
10.标签页里面的内容为businessManagement.vue
<template>
<div>
<p>厂商管理</p>
<p><input type="text"></p>
</div>
</template>
<script>
export default {
name: 'BasicContainer'
}
</script>
<style scoped>
</style>
11.标签页里面的内容为HomePage.vue
<template>
<div>
<p>首页</p>
<p><input type="text"></p>
</div>
</template>
<script>
export default {
name: "HomePage"
}
</script>
<style scoped>
</style>
12.标签页里面的内容为userManagement.vue
<template>
<div>
<p>用户管理</p>
</div>
</template>
<script>
export default {
name: 'BasicRadio'
}
</script>
<style scoped>
</style>
更多推荐
已为社区贡献4条内容
所有评论(0)