目录

前言

 首先我们来看一下效果图:

 一、layout布局

1.创建头部(header.vue)

2.创建侧边导航(sliber.vue)

二、路由嵌套

1.配置layout和路由

总结


前言

在后台系统设计中,经常会使用layout布局以及路由,想知道具体怎么使用,继续往下看看吧~


 首先我们来看一下效果图:

 上面的效果图主要有三部分组成:头部、侧边导航、主要内容区域。当我们点击页面时,切换主要内容区域,所以需要使用layout布局。侧边导航又有子菜单,所以我们需要路由嵌套。分析完了,那我们开始吧~

首先我们要在src文件夹下面,新建一下文件夹和文件:

 一、layout布局

1.创建头部(header.vue)

头部如下图:

 思路:分为左边的名称,右边的登录名称和注销图标,这种左右布局肯定要使用flex布局啦~;进入首页后我们要使用localStorage把登陆时存储的用户名取出来显示在右边登录名的地方,当用户点击注销图标的时候,清除localStorage,并跳转回登陆页面。下面直接上代码:

<template>
  <div class="header_container ">
    <div class="logo white_color">
      <span>XXX后台管理系统</span>
    </div>
    <div class="user_info white_color">
      <span @click="outLogin"> <i class="el-icon-warning-outline"
           style="margin-right: 15px"></i></span>
      <span>{{user}}</span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: ''
    }
  },
  mounted() {
    this.info()
  },
  methods: {
    info() {
      var account = JSON.parse(localStorage.getItem('token'))
      console.log(account, 'account')
      this.user = account.account
    },
    outLogin() {
      this.user = ''
      localStorage.removeItem('token')
      this.$router.push('/login')
    }
  }
}
</script>

<style lang='scss'>
</style>

 此处的css我写在了公共样式文件里面,你需要,在src下创建一下文件夹以及文件:

 然后在public.scss中输入以下内容:

$mian_color: rgb(179, 162, 199);
$weightMain_color:rgb(96, 74, 123);
$contrast_color:white;

.mian_color{
  color: $mian_color;
}

.white_color{
color:$contrast_color
}

body{
  margin: 0;
}
.header_container {
  position: flex;
  top: 0;
  left: 0;
  width: 100%;
  background: $mian_color;
  font-size: 12px;
  display: flex;
  justify-content: space-between;
  .logo {
    font-size: 24px;
    font-weight: 600px;
  }
}
.el-header {
  background-color:$mian_color !important;
  color: #333;
  line-height: 60px;
}
.el-aside {
  height: calc(100vh - 60px) !important;
  background: $weightMain_color;
}
.el-menu {
  border-right:0 !important
}

 然后在App.vue中引入这两个样式,输入以下代码:

<style lang='scss'>
@import './styles/public.scss';
@import './styles/index.scss';
</style>

 2.创建侧边导航(sliber.vue)

侧边导航如下图:

 思路:样式就是elmentUI的侧边导航。重点是树状菜单的组合,后端返回的肯定是数组中包裹对象,所以我们需要根据其中的pid判断是哪一个一级菜单的子集。下面直接上代码:

<template>

  <div class="asideNav">
    <el-menu :default-active="$route.path"
             class="el-menu-vertical"
             router
             unique-opened
             :collapse="iscollapse"
             :collapse-transition="false"
             active-text-color='#FFC000'
             background-color="#604A7B"
             text-color="#fff">
      <div v-for="(item,i) in lastMeun"
           :key="i">
        <el-submenu :index="item.prouter"
                    v-if="item.children">
          <template slot="title">
            <i :class="item.icon"></i>
            <span class="tohide">{{item.name}}</span>
          </template>
          <el-menu-item :index="val.crouter"
                        v-for="val in item.children"
                        :key="val.id">
            <i class="el-icon-s-help"></i>
            <span>{{val.name}}</span>
          </el-menu-item>
        </el-submenu>
        <el-menu-item :index="item.prouter"
                      v-else>
          <i :class="item.icon"></i>
          <span slot="title">{{item.name}}</span>
        </el-menu-item>
      </div>

    </el-menu>
  </div>

</template>

<script>
export default {
  data() {
    return {
      defaultActive: '/home',
      iscollapse: false,
      logourl: require('../../assets/logo.png'),
      username: null,
      show: false,
      lastMeun: [],
      pMeun: [],
      cMeun: [],
      meunList: [
        { id: '1', pid: '', name: '首页', router: '/home', icon: 'el-icon-eleme' },
        { id: '2', pid: '', name: '列表管理', router: '/list', icon: 'el-icon-s-tools' },
        { id: '3', pid: '', name: '产品管理', router: '/proudct', icon: 'el-icon-star-on' },
        { id: '4', pid: '', name: '长度管理', router: '/length', icon: 'el-icon-edit' },
        { id: '5', pid: '3', name: '产品管理one', router: '/proudct/one', icon: 'el-icon-edit' },
        { id: '6', pid: '3', name: '产品管理two', router: '/proudct/two', icon: 'el-icon-edit' },
        {
          id: '7',
          pid: '3',
          name: '产品管理three',
          router: '/proudct/three',
          icon: 'el-icon-edit'
        },
        { id: '8', pid: '3', name: '产品管理four', router: '/proudct/four', icon: 'el-icon-edit' },
        { id: '9', pid: '', name: '双数管理', router: '/double', icon: 'el-icon-bell' },
        { id: '10', pid: '', name: '数据管理', router: '/data', icon: 'el-icon-info' },
        { id: '11', pid: '10', name: '数据管理one', router: '/data/one', icon: 'el-icon-edit' },
        { id: '12', pid: '10', name: '数据管理two', router: '/data/two', icon: 'el-icon-edit' }
      ]
    }
  },
  mounted() {
    this.info()
  },
  methods: {
    info() {
      var pMeun = [] //父级菜单
      var cMeun = [] //子菜单
      if (this.meunList.length > 0) {
        //有数据则进行下一步
        //遍历菜单列表,如果没有pid(父级id,没有表示他是一级菜单),则放进pMeun,有则放进cMeun
        this.meunList.forEach((item) => {
          if (!item.pid) {
            pMeun.push({
              id: item.id,
              name: item.name,
              icon: item.icon,
              prouter: item.router,
              // meta: { title: i.name, icon: i.icon, access: 1 },
              children: []
            })
          } else {
            cMeun.push(item)
          }
        })
        console.log(pMeun, cMeun)
        //判断pMeun和cMeun中id和pid是否相等,相等则将该项加入对应pMeun的children中
        pMeun.forEach((pitem) => {
          cMeun.forEach((citem) => {
            if (citem.pid == pitem.id) {
              // console.log(pitem, '11')
              pitem.children.push({
                id: citem.id,
                name: citem.name,
                crouter: citem.router
                //  meta: { title: i.name, icon: i.icon, access: 1 },
              })
            }
          })
        })
        //如果pMeun中的children没有数据的,则删除该children属性
        pMeun.forEach((item, index) => {
          if (!item.children.length) {
            delete pMeun[index].children
          }
        })

        console.log(pMeun, 'pMeun')
        this.lastMeun = pMeun //赋值给菜单数据源
      } else {
        retrun
      }
    },
    setcollapse() {
      this.iscollapse = !this.iscollapse
      this.$nextTick(() => {
        if (this.iscollapse) {
          $('#logo').css('width', '64px')
          $('.el-aside').css('width', 'auto')
          $('.tohide,.el-submenu__title .el-icon-arrow-right').css('display', 'none')
        } else {
          $('#logo').css('width', 'auto')
          $('.el-aside').css('width', '152px')
          $('.tohide,.el-submenu__title .el-icon-arrow-right').css('display', 'inline')
        }
      })
    }
  }
}
</script>

<style lang='scss' scoped>
.asideNav {
  text-align: left;
}
</style>

 最后,要在layout文件夹下面的index.vue写下嵌套的结构,代码如下:

<template>

  <el-container class="contanier_box">
    <!-- 头部 -->
    <el-header>
      <Header></Header>
    </el-header>
    <!-- 头部下面的内容 -->
    <el-container>
      <!-- 侧边导航 -->
      <el-aside width='205px'
                class="sliber_box">
        <Sliber></Sliber>
      </el-aside>
      <!-- 主要内容 -->
      <el-main>
        <router-view></router-view>
      </el-main>
    </el-container>
  </el-container>

</template>

<script>
import Sliber from './components/sliber.vue'
import Header from './components/header.vue'
export default {
  components: {
    Sliber,
    Header
  }
}
</script>

<style lang="scss" scoped>
</style>

二、路由嵌套

1.配置layout和路由

打开router文件夹下面的index.js引入layout,如下图:

index文件完整代码如下:

import Vue from 'vue'
import Router from 'vue-router'
// 引入自己写的layout
import Layout from '@/layout'
Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',//根目录路由为/
      component: Layout,//指定使用Layout组件布局
      redirect: '/home',//重定向至/home页面
      children: [{//子菜单信息
        path: '/home',//路径
        name: 'home',
        component: () => import('@/views/home'),//指定组件
        meta: { title: '首页', access: 0, affix: true }
      }]
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('@/views/login')
    },
    {
      path: '/list',
      component: Layout,
      children: [{
        path: "/list",
        name: 'list',
        component: () => import('@/views/list'),
        meta: { title: 'list管理', access: 0 }
      }]

    },
    {
      path: '/length',
      component: Layout,
      children: [{
        path: "/length",
        name: 'length',
        component: () => import('@/views/length'),
        meta: { title: 'length管理', access: 0 }
      }]

    },
    {
      path: '/double',
      component: Layout,
      children: [{
        path: "/double",
        name: 'double',
        component: () => import('@/views/double'),
        meta: { title: 'double管理', access: 0 }
      }]

    },
    {
      path: '/proudct',
      component: Layout,
      redirect: '/proudct/one',
      meta: { title: '产品管理' },
      children: [{
        path: '/proudct/one',
        name: 'proudct_one',
        component: () => import('@/views/proudct/one'),
        meta: { title: '产品管理1', access: 0, affix: true }
      },
      {
        path: '/proudct/two',
        name: 'proudct_two',
        component: () => import('@/views/proudct/two'),
        meta: { title: '产品管理2', access: 0, affix: true }
      },
      {
        path: '/proudct/three',
        name: 'proudct_three',
        component: () => import('@/views/proudct/three'),
        meta: { title: '产品管理3', access: 0, affix: true }
      },
      {
        path: '/proudct/four',
        name: 'proudct_four',
        component: () => import('@/views/proudct/four'),
        meta: { title: '产品管理4', access: 0, affix: true }
      }]
    },
    {
      path: '/data',
      component: Layout,
      redirect: '/data/one',
      meta: { title: '数据管理' },
      children: [{
        path: '/data/one',
        name: 'data_one',
        component: () => import('@/views/data/one'),
        meta: { title: '数据管理1', access: 0, affix: true }
      },
      {
        path: '/data/two',
        name: 'data_two',
        component: () => import('@/views/data/two'),
        meta: { title: '数据管理2', access: 0, affix: true }
      }]
    },
  ]
})

 注意:当然,路由中涉及的页面也要像创建首页一样创建好,否则不能运行成功哟


总结

以上就是今天要讲的内容,本文代码量大,但其实知识点就只有两个:路由嵌套和layout布局,千万不要被代码吓到了哟~。

如果你只想搭建项目得框架,那么走到这一步就已经成功了哟,接下里得几章是扩展功能得~

上一章vue+elementUI后台系统(第五章:权限设置)

下一章vue+elementUI后台系统(第七章:路由重定向)

Logo

前往低代码交流专区

更多推荐