• 【前端】Vue+Element UI案例:通用后台管理系统-导航栏



    参考视频: VUE项目,VUE项目实战,vue后台管理系统,前端面试,前端面试项目

    案例链接
    【前端】Vue+Element UI案例:通用后台管理系统-导航栏(视频p1-16)https://blog.csdn.net/karshey/article/details/127640658
    【前端】Vue+Element UI案例:通用后台管理系统-Header+导航栏折叠(p17-19)https://blog.csdn.net/karshey/article/details/127652862
    【前端】Vue+Element UI案例:通用后台管理系统-Home组件:卡片、表格(p20-22)https://blog.csdn.net/karshey/article/details/127674643
    【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表准备:axios封装、mock数据模拟实战(p23-25)https://blog.csdn.net/karshey/article/details/127735159
    【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表:折线图、柱状图、饼状图(p27-30)https://blog.csdn.net/karshey/article/details/127737979
    【前端】Vue+Element UI案例:通用后台管理系统-面包屑、tag栏(p31-35)https://blog.csdn.net/karshey/article/details/127756733
    【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Form表单填写、Dialog对话框弹出(p36-38)https://blog.csdn.net/karshey/article/details/127787418
    【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Table表格增删查改、Pagination分页、搜索框(p39-42)https://blog.csdn.net/karshey/article/details/127777962
    【前端】Vue+Element UI案例:通用后台管理系统-登陆页面Login(p44)https://blog.csdn.net/karshey/article/details/127795302
    【前端】Vue+Element UI案例:通用后台管理系统-登陆页面功能:登录权限跳转、路由守卫、退出(p45-46)https://blog.csdn.net/karshey/article/details/127849502
    【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由(p47-48)https://blog.csdn.net/karshey/article/details/127865621
    【前端】Vue+Element UI案例:通用后台管理系统-项目总结https://blog.csdn.net/karshey/article/details/127867638

    目标

    在这里插入图片描述

    • 悬停效果
    • 点击效果
    • 其他:点击展开和收缩
    • 动态显示“首页”“商品管理”等
    • 有路由跳转

    其实是项目的导航栏组件。只打算看导航栏部分的可以跳过1.其他准备

    代码

    0.数据

    我们把它单独放到一个MenuData.js中,然后用export default暴露出来。

    {
          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'
            }
          ]
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    1.其他准备

    注意要查看官方文档:官方文档

    全局引入Element UI

    先安装Element UI:

    npm i element-ui -S
    
    • 1

    全局引入:在main.js中

    import ElementUI from 'element-ui'
    
    Vue.use(ElementUI)
    
    • 1
    • 2
    • 3

    路由配置

    这里我们先配置Home页面(会显示导航栏的页面)。官方文档:Vue Router

    安装:这里的版本是3.6.5
    ps:可以在npm网站上查到包的所有版本,我们这里要的是3.x.x的最新版。

    npm install vue-router@3.6.5
    
    • 1

    路由的配置:目前只配置了Main组件的

    import Vue from "vue";
    import VueRouter from "vue-router";
    import Main from '../Views/Main'
    
    Vue.use(VueRouter)
    
    const routes=[
        // 主路由
        {
            path:'/',
            component:Main
        }
    ]
    
    const router = new VueRouter({
        routes
    })
    
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    目前的依赖
    当前的package.json文件的dependencies应当如下:

    "dependencies": {
        "core-js": "^3.8.3",
        "element-ui": "^2.15.10",
        "vue": "^2.6.14",
        "vue-router": "^3.6.5"
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当前的main.js

    import Vue from 'vue'
    import App from './App.vue'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css';
    import router from './router/index'
    
    Vue.config.productionTip = false
    Vue.use(ElementUI)
    
    new Vue({
      router,
      render: h => h(App),
    }).$mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Main.vue布局结构
    要的是这个布局:
    在这里插入图片描述
    找到对应代码:

    <el-container>
      <el-aside width="200px">Asideel-aside>
      <el-container>
        <el-header>Headerel-header>
        <el-main>Mainel-main>
      el-container>
    el-container>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    把它放到Main.vue里。

    App.vue如下:

    <template>
      <div id="app">
        <router-view>router-view>
      div>
    template>
    
    <script>
    export default {
    }
    script>
    
    <style>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    效果:
    在这里插入图片描述
    接下来我们写一个组件:CommonAside.vue,把导航栏写在这个组件里,再把组件放到Aside中。

    因此放了布局的Main.vue如下:

    <template>
        <el-container>
            <el-aside width="200px">
                <common-aside/>
            el-aside>
            <el-container>
                <el-header>Headerel-header>
                <el-main>Mainel-main>
            el-container>
        el-container>
    template>
    
    <script>
    import CommonAside from '../components/CommonAside.vue'
    export default {
        data(){
            return{}
        },
        components:{
            CommonAside
        }
    }
    script>
    
    <style>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    组件CommonAside如下:

    <template>
      
    template>
    
    <script>
    export default {
    
    }
    script>
    
    <style>
    
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接下来就是本文正题:导航栏。

    2.结构

    Element UI文档
    我们现在Element UI官方文档上找到类似的导航结构:就是你了!
    在这里插入图片描述
    阅读代码,我们不难发现代码分为“展开收起”部分和“导航”部分,我们要的是导航部分。把代码对着我们的目标稍作调整得到:

    <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"
        :collapse="isCollapse">
        <el-menu-item index="2">
            <i class="el-icon-menu">i>
            <span slot="title">导航一span>
        el-menu-item>
        <el-submenu index="1">
            <template slot="title">
                <i class="el-icon-location">i>
                <span slot="title">导航二span>
            template>
            <el-menu-item-group>
                <span slot="title">分组一span>
                <el-menu-item index="1-1">选项1el-menu-item>
                <el-menu-item index="1-2">选项2el-menu-item>
            el-menu-item-group>
        el-submenu>
    el-menu>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    效果:
    在这里插入图片描述

    3.动态显示数据

    导航栏分为一级导航栏和二级导航栏,目标中的 其他-页面1 就是二级导航栏,首页、商品管理、用户管理 都是一级导航栏。

    一级和二级的区别在于:数据中是否有children属性,如果有,那它的children属性就是二级导航。所以这里要用到计算属性

    computed:{
       noChildren(){
           // 如果没有children则返回true,会被过滤器留下
           return this.MenuData.filter(item=>!item.children)
       },
       hasChildren(){
           return this.MenuData.filter(item=>item.children)
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    一级导航栏的循环显示:

    
    
     <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    效果:
    在这里插入图片描述
    二级导航栏也是类似做法:

    <el-submenu v-for="item in hasChildren" :key="item.name" :index="item.name">
            <template slot="title">
                <i :class="`el-icon-${item.icon}`">i>
                <span slot="title">{{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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    效果:
    在这里插入图片描述

    4.主题:背景色,点击悬停效果

    再次打开文档,找到自定义颜色部分:
    在这里插入图片描述
    显然是这里:我们把它直接复制粘贴。
    在这里插入图片描述
    则标签如下:

    <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">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    效果:就是这样!
    在这里插入图片描述

    5.去除padding

    在浏览器中F12可知,padding是由body等标签自动带有的,我们只需要在App.vue中把它们清除即可(reset)。

    html,
    body,
    h3,
    p {
      margin: 0;
      padding: 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    6.去除下拉框

    这里我们先安装less:这样写CSS可以嵌套,更加方便。

    npm install less less-loader --save
    
    • 1

    浏览器F12,显然有下拉框的这个类是:el-menu
    在这里插入图片描述
    把el-menu设置成height:100vh即可。

    7.标题

    html:

    
    <h3>通用后台管理系统h3>
    
    • 1
    • 2

    css:

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    效果:
    在这里插入图片描述

    8.路由跳转

    添加点击事件:

    <el-menu-item 
    @click="clickItem(item)" 
    v-for="item in noChildren" 
    :key="item.name" 
    :index="item.name">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
        <el-menu-item @click="clickItem(subItem)" :index="subItem.name">{{ subItem.label }}el-menu-item>
    el-menu-item-group>
    
    • 1
    • 2
    • 3

    js:

    clickItem(item){
       // 防止自己跳自己的报错
       if(this.$route.path!==item.path&&!(this.$route.path==='/home'&&(item.path==='/'))){
           this.$router.push(item.path)
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    不过目前只有一个路由。

    总代码

    组件CommonAside.vue

    <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="clickItem(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 slot="title">{{ item.label }}span>
                template>
                <el-menu-item-group @click="clickItem(subItem)" 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>
    template>
    
    <style lang="less" scoped>
    .el-menu-vertical-demo:not(.el-menu--collapse) {
        width: 200px;
        min-height: 400px;
    }
    
    .el-menu{
        height:100vh;
    
        h3{
            text-align: center;
            line-height: 48px;
            color: #fff;
            font-size: 16px;
            font-weight: 400;
        }
    }
    style>
    
    <script>
    import MenuData from '../data/MenuData'
    export default {
        data() {
            return {
                isCollapse: false,
                MenuData
            };
        },
        methods: {
            handleOpen(key, keyPath) {
                console.log(key, keyPath);
            },
            handleClose(key, keyPath) {
                console.log(key, keyPath);
            },
            clickItem(item){
                // 防止自己跳自己的报错
                if(this.$route.path!==item.path&&!(this.$route.path==='/home'&&(item.path==='/'))){
                    this.$router.push(item.path)
                }
            }
        },
        computed: {
            noChildren() {
                // 如果没有children则返回true,会被过滤器留下
                return this.MenuData.filter(item => !item.children)
            },
            hasChildren() {
                return this.MenuData.filter(item => item.children)
            }
        }
    }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    文件结构

    在这里插入图片描述

    参考

    VUE项目,VUE项目实战,vue后台管理系统,前端面试,前端面试项目:p1-16

  • 相关阅读:
    015-JAVA类与对象详细介绍
    MT3036 第一节离数课后
    kali的三层镜像是什么意思
    编译原理总结
    C++ 小游戏 视频及资料集(八)
    Oracle中新建数据表的两种方法
    http1和http2的主要区别
    登录拦截器从session中获取信息失败(session失效问题)
    Java---Java Web---JSP
    CSRF漏洞分析
  • 原文地址:https://blog.csdn.net/karshey/article/details/127640658