Vue2项目练手------通用后台管理项目
路由限制重复跳转
路由重复跳转会出现bug
解决路由重复bug问题:
javascript
clickMenu(item){
// console.log(item)
// console.log(this.$route.path)
// 当页面的路由与跳转的路由不一致才允许跳转
if(this.$route.path!==item.path && !(this.$route.path==='/home'&&(item.path==='/'))){
this.$router.push(item.path)
}
}
CommonAside.vue
html
<template>
<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
:collapse="isCollapse" background-color="#545c64" text-color="#fff"
active-text-color="#ffd04b">
<h3>通用后台管理系统</h3>
<el-menu-item @click="clickMenu(item)" v-for="item in noChildren" :key="item.name" :index="item.name">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{item.label}}</span>
</el-menu-item>
<el-submenu :index="item.label" v-for="item in hasChildren" :key="item.label">
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{item.label}}</span>
</template>
<el-menu-item-group>
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path" :key="subItem.path" v-for="subItem in item.children">
{{subItem.label}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
.el-menu{
height: 100vh; //占据页面高度100%
h3{
color: #fff;
text-align: center;
line-height: 48px;
font-size: 16px;
font-weight: 400;
}
}
</style>
<script>
export default {
data() {
return {
isCollapse: false,
menuData:[
{
path:'/',
name:"home",
label:"首页",
icon:"s-home",
url:'Home/Home'
},
{
path:'/mall',
name:"mall",
label:"商品管理",
icon:"video-play",
url:'MallManage/MallManage'
},
{
path:'/user',
name:"user",
label:"用户管理",
icon:"user",
url:'userManage/userManage'
},
{
label:"其他",
icon:"location",
children:[
{
path:'/page1',
name:"page1",
label:"页面1",
icon:"setting",
url:'Other/PageOne'
},
{
path:'/page2',
name:"page2",
label:"页面2",
icon:"setting",
url:'Other/PageTwo'
},
]
},
]
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
clickMenu(item){
// console.log(item)
// console.log(this.$route.path)
// 当页面的路由与跳转的路由不一致才允许跳转
if(this.$route.path!==item.path && !(this.$route.path==='/home'&&(item.path==='/'))){
this.$router.push(item.path)
}
}
},
mounted() {
console.log(this.$route.path)
},
computed:{
//没有子菜单的数据
noChildren(){
return this.menuData.filter(item=>!item.children)
},
//有子菜单数组
hasChildren(){
return this.menuData.filter(item=>item.children)
}
}
}
</script>
顶部header组件搭建与样式修改
右边用户菜单栏
使用的组件
图片
CommonHeader.vue
html
<template>
<div class="header-container">
<div class="l-content">
<el-button icon="el-icon-menu" size="mini"></el-button>
<!-- 面包屑-->
<span class="text">首页</span>
</div>
<div class="r-content">
<el-dropdown>
<span class="el-dropdown-link">
<img src="@/assets/user.webp" alt="">
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
export default {
name: "CommonHeader",
}
</script>
<style scoped lang="less">
.header-container {
height: 60px;
background-color: #333;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
.text {
color: #fff;
font-size: 14px;
margin-left: 10px;
}
.r-content{
img{
width: 40px;
height: 40px;
border-radius: 50%;
}
}
}
</style>
Vuex实现左侧折叠
文件目录
store/index.js
javascript
import Vue from 'vue'
import Vuex from 'vuex'
import tab from './tab'
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
tab
}
})
store/tab.js
javascript
export default {
state:{
isCollapse:false //控制菜单的展开还是收起
},
mutations:{
// 修改菜单展开收起的方法
collapseMenu(state){
state.isCollapse=!state.isCollapse
}
}
}
main.js
javascript
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import router from "@/router";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'
import store from '@/store'
Vue.config.productionTip = false
Vue.use(VueRouter)
Vue.use(ElementUI)
new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
CommonHeader.vue
html
<template>
<div class="header-container">
<div class="l-content">
<el-button icon="el-icon-menu" size="mini" @click="handleMenu"></el-button>
<!-- 面包屑-->
<span class="text">首页</span>
</div>
<div class="r-content">
<el-dropdown>
<span class="el-dropdown-link">
<img src="@/assets/user.webp" alt="">
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
export default {
name: "CommonHeader",
methods:{
handleMenu(){
this.$store.commit('collapseMenu')
}
}
}
</script>
<style scoped lang="less">
.header-container {
height: 60px;
background-color: #333;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
.text {
color: #fff;
font-size: 14px;
margin-left: 10px;
}
.r-content{
img{
width: 40px;
height: 40px;
border-radius: 50%;
}
}
}
</style>
CommonAside.vue
html
<template>
<el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
:collapse="isCollapse" background-color="#545c64" text-color="#fff"
active-text-color="#ffd04b">
<h3>{{isCollapse?'后台':'通用后台管理系统'}}</h3>
<el-menu-item @click="clickMenu(item)" v-for="item in noChildren" :key="item.name" :index="item.name">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{item.label}}</span>
</el-menu-item>
<el-submenu :index="item.label" v-for="item in hasChildren" :key="item.label">
<template slot="title">
<i :class="`el-icon-${item.icon}`"></i>
<span slot="title">{{item.label}}</span>
</template>
<el-menu-item-group>
<el-menu-item @click="clickMenu(subItem)" :index="subItem.path" :key="subItem.path" v-for="subItem in item.children">
{{subItem.label}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
.el-menu{
height: 100vh; //占据页面高度100%
h3{
color: #fff;
text-align: center;
line-height: 48px;
font-size: 16px;
font-weight: 400;
}
}
</style>
<script>
export default {
data() {
return {
menuData:[
{
path:'/',
name:"home",
label:"首页",
icon:"s-home",
url:'Home/Home'
},
{
path:'/mall',
name:"mall",
label:"商品管理",
icon:"video-play",
url:'MallManage/MallManage'
},
{
path:'/user',
name:"user",
label:"用户管理",
icon:"user",
url:'userManage/userManage'
},
{
label:"其他",
icon:"location",
children:[
{
path:'/page1',
name:"page1",
label:"页面1",
icon:"setting",
url:'Other/PageOne'
},
{
path:'/page2',
name:"page2",
label:"页面2",
icon:"setting",
url:'Other/PageTwo'
},
]
},
]
};
},
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
clickMenu(item){
// console.log(item)
// console.log(this.$route.path)
// 当页面的路由与跳转的路由不一致才允许跳转
if(this.$route.path!==item.path && !(this.$route.path==='/home'&&(item.path==='/'))){
this.$router.push(item.path)
}
}
},
mounted() {
console.log(this.$route.path)
},
computed:{
//没有子菜单的数据
noChildren(){
return this.menuData.filter(item=>!item.children)
},
//有子菜单数组
hasChildren(){
return this.menuData.filter(item=>item.children)
},
isCollapse(){
return this.$store.state.tab.isCollapse
}
}
}
</script>
Main.vue
html
<template>
<div>
<el-container>
<el-aside width="auto">
<CommonAside></CommonAside>
</el-aside>
<el-container>
<el-header>
<CommonHeader></CommonHeader>
</el-header>
<el-main>
<!-- 路由出口,路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import CommonAside from "@/components/CommonAside.vue";
import CommonHeader from "@/components/CommonHeader.vue";
export default {
name: "Main",
components:{CommonAside,CommonHeader}
}
</script>
<style scoped>
.el-header{
padding: 0;
margin: 0;
}
.el-menu{
border-right: none;
}
</style>