【Vue2+Element ui通用后台】左侧菜单实现

主体布局搭建

我们在 Container 布局容器,找到有左侧、头部、和主体部分的布局,直接复制代码到 Main.vue 中:

<template>
  <div>
    <el-container>
      <el-aside width="200px">Aside</el-aside>
      <el-container>
        <el-header>Header</el-header>
        <el-main><router-view></router-view></el-main>
      </el-container>
    </el-container>
  </div>
</template>

在这里插入图片描述

左侧菜单搭建

导航菜单中找到我们需要的直接复制示例代码到项目中即可

我们在 components 中新建 CommonAside.vue ,做为左侧菜单的组件,把复制的代码放进去

<template>
  <div class="hello">
    <el-menu
        default-active="2"
        class="el-menu-vertical-demo"
        @open="handleOpen"
        @close="handleClose"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b">
      <el-submenu index="1">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span>导航一</span>
        </template>
        <el-menu-item-group>
          <template slot="title">分组一</template>
          <el-menu-item index="1-1">选项1</el-menu-item>
          <el-menu-item index="1-2">选项2</el-menu-item>
        </el-menu-item-group>
        <el-menu-item-group title="分组2">
          <el-menu-item index="1-3">选项3</el-menu-item>
        </el-menu-item-group>
        <el-submenu index="1-4">
          <template slot="title">选项4</template>
          <el-menu-item index="1-4-1">选项1</el-menu-item>
        </el-submenu>
      </el-submenu>
      <el-menu-item index="2">
        <i class="el-icon-menu"></i>
        <span slot="title">导航二</span>
      </el-menu-item>
      <el-menu-item index="3" disabled>
        <i class="el-icon-document"></i>
        <span slot="title">导航三</span>
      </el-menu-item>
      <el-menu-item index="4">
        <i class="el-icon-setting"></i>
        <span slot="title">导航四</span>
      </el-menu-item>
    </el-menu>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isCollapse: true
    };
  },
  methods: {
    handleOpen(key, keyPath) {
      console.log(key, keyPath);
    },
    handleClose(key, keyPath) {
      console.log(key, keyPath);
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
</style>


然后在 Main.vue 中引入组件

<template>
  <div>
    <el-container>
      <el-aside width="200px">
        <CommonAside />
      </el-aside>
      <el-container>
        <el-header>Header</el-header>
        <el-main><router-view></router-view></el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>
import CommonAside from "@/components/CommonAside";
export default {
  name: "Main",
  components:{
    CommonAside
  }
}
</script>

<style scoped>

</style>

运行项目现在的样式:
在这里插入图片描述
我们修改默认代码,使用 for 循环动态渲染成我们所需要的导航数据:

<template>
  <div class="hello">
    <el-menu
        default-active="2"
        class="el-menu-vertical-demo"
        @open="handleOpen"
        @close="handleClose"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b">

      <el-menu-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 v-for="item in hasChildren" :key="item.name" :index="item.name">
        <template slot="title">
          <i :class="`el-icon-${item.icon}`"></i>
          <span>{{item.label}}</span>
        </template>
        <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
          <el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item>
        </el-menu-item-group>
      </el-submenu>
    </el-menu>
  </div>
</template>

<script>
export default {
  data() {
    return {
      isCollapse: true,
      menuData: [
        {
          path: '/',
          name: 'home',
          label: '首页',
          icon: 's-home',
          url: 'Home/home'
        },
        {
          path: '/mall',
          name: 'mall',
          label: '商品管理',
          icon: 'video-play',
          url: 'MallManage/MallManager'
        },
        {
          path: '/user',
          name: 'user',
          label: '用户管理',
          icon: 'user',
          url: 'UserManage/UserManager'
        },
        {
          label: '其他',
          icon: 'location',
          name: 'other',
          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);
    }
  },
  computed:{
    // 没有子菜单
    noChildren(){
      return this.menuData.filter(item => !item.children)
    },
    // 有子菜单
    hasChildren(){
      return this.menuData.filter(item => item.children)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
</style>

运行程序:
在这里插入图片描述

对代码进行分析:我们使用计算属性分为有子菜单和没有子菜单的两部分,然后分别遍历

我们用到了图标:Icon,使用方法就是在 <i> 中使用对应 class 即可,我们观察到图标的前边都是一样的,所以我们使用 ES6的模板语法,只改变后边的名称即可
在这里插入图片描述
由于我们需要修改左侧菜单的样式,我们可以使用 less(less官方文档),我们需要先下载安装执行npm i less@4.1.2

还需要安装npm i less-loader@6.0.0

之后修改 CommonAside.vue 中代码,增加一个标题,然后修改样式如下:

<template>
  <div class="hello">
    <el-menu
        default-active="2"
        class="el-menu-vertical-demo"
        @open="handleOpen"
        @close="handleClose"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b">
      <h3>通用后台管理</h3>
      ......
    </el-menu>
  </div>
</template>

<script>
......
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
.el-menu{
  height: 100vh;
  h3{
        color: #fff;
	    text-align: center;
    	line-height: 48px;
    	font-size: 16px;
   	 	font-weight: 400;
  }
}
</style>

现在样式是这样的,左边有默认的边距,所以需要修改 App.vue 去掉边距

<template>
  <div id="app">
    <!-- 路由出口 -->
    <!-- 路由匹配到的组件将渲染在这里 -->
    <router-view></router-view>
  </div>
</template>

<script>
</script>

<style lang="less">
html,body,h3{
  margin: 0;
  padding: 0;
}
</style>

运行效果如下:
在这里插入图片描述

左侧菜单跳转

在 CommonAside 中我们的菜单数据中已经有了跳转路径,我们需要加到 index.js 中

这里的 path 就复制 CommonAside 中对应菜单的 path 即可

import Vue from 'vue'
......

//1、创建组件
import Home from '../views/Home';
import User from '../views/User';
import Main from '../views/Main';
import Mall from '../views/Mall';
import PageOne from '../views/PageOne';
import PageTwo from '../views/PageTwo';
//2、将路由与组件进行映射
const routes = [
    {
        //主路由
        path: '/',
        component: Main,
        children: [
            { path: 'home', component: Home },// 主页
            { path: 'user', component: User },// 用户管理
            { path: 'mall', component: Mall },// 商品管理
            { path: 'page1', component: PageOne },// 页面1
            { path: 'page2', component: PageTwo },// 页面2
        ]
    }
]
//3、创建router实例
......


这样当我们在浏览器地址栏修改地址时,页面就会展示对应的页面了

在这里插入图片描述
下面完成点击左侧菜单进行跳转,所以需要给菜单添加 click 事件,传入点击的菜单的数据,使用 router 进行跳转

<template>
  <div class="hello">
    <el-menu
        default-active="2"
        class="el-menu-vertical-demo"
        @open="handleOpen"
        @close="handleClose"
        background-color="#545c64"
        text-color="#fff"
        active-text-color="#ffd04b">
      <h3>通用后台管理</h3>
      <el-menu-item v-for="item in noChildren" :key="item.name" :index="item.name" @click="menuClick(item)">
        <i :class="`el-icon-${item.icon}`"></i>
        <span slot="title">{{item.label}}</span>
      </el-menu-item>

      <el-submenu v-for="item in hasChildren" :key="item.name" :index="item.name">
        <template slot="title">
          <i :class="`el-icon-${item.icon}`"></i>
          <span>{{item.label}}</span>
        </template>
        <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
          <el-menu-item :index="subItem.name">{{subItem.label}}</el-menu-item>
        </el-menu-item-group>
      </el-submenu>
    </el-menu>
  </div>
</template>

<script>
export default {
  ......
  methods: {
    ......
    menuClick(item) {
      this.$router.push(item.path)
    }
  },
  ......
}
</script>

index.js 中需要增加redirect:'/home',这样当以为首页的路径是 /,当点击时需要重定向到 home 页面

const routes = [
    {
        //主路由
        path: '/',
        component: Main,
        redirect:'/home',
        children: [
            { path: 'home', component: Home },// 主页
            { path: 'user', component: User },// 用户管理
            { path: 'mall', component: Mall },// 商品管理
            { path: 'page1', component: PageOne },// 页面1
            { path: 'page2', component: PageTwo },// 页面2
        ]
    }
]

在这里插入图片描述
然后我们解决一个问题,当我们已经点击了商品管理时,当再次点击一次商品管理时会报错,这是因为 router 限制了我们不能重复跳转,如果重复跳转就会有这个提示
在这里插入图片描述
所以我们需要在跳转时进行判断,如果需要跳转的路径和当前路径相同就不进行跳转

menuClick(item) {
      // 当页面的路由与跳转的路由不一致才进行跳转
      if(this.$route.path !== item.path && !(this.$route.path === '/home' && item.path === '/')){
        this.$router.push(item.path)
      }
    }
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值