上篇对该项目作了个总述 :Vue + Element-ui实现后台管理系统(1) --- 总述javascript
这篇主要讲解 项目搭建 + 后台⾸⻚布局实现 :php
总体效果
css
后台首页按布局一共包含3个部分: 一、左侧栏部分 二、头部部分 三、内容部分。html
说明
在整个后台管理系统中,左侧栏和头部部分是应该一直在页面中展现的,因此对于每一个页面这两个组件都应该存在,而 内容部分 才是经过router的跳转而跳到不一样的组件。vue
下面先把整个项目搭建一下,而后再来说解上面三个部分java
#一、安装node (node -v查询版本号) node 安装 #二、安装淘宝镜像 npm install -g cnpm --registry=https://registry.npm.taobao.org #三、安装 webpack,以全局的方式安装 npm install webpack -g #四、全局安装vue以及脚手架vue-cli npm install @vue/cli -g --unsafe-perm #五、建立vue项目 mall-manage-system是你起的项目名称 vue create mall-manage-system #六、运行当前项目 这个整个项目就搭建好了 npm run serve
在安装中可能会存在的问题node
一、node升级后,项目中的node-sass报错的问题webpack
二、npm install 报错,提示 gyp ERR! stack Error: EACCES: permission denied 解决方法ios
若是上面都安装成功,那么经过 npm run serve 就可用启动该项目了。这里把简单说明下一些公共配置git
一、main.js(主文件)
import Vue from 'vue' import App from './App.vue' import router from './router' //引入 vue-router import store from './store' //引入 vuex // 全局配置 import '@/assets/scss/reset.scss' //全局样式 import 'element-ui/lib/theme-chalk/index.css' //element-ui样式 import http from '@/api/config' //axios import './mock' // mockjs // 第三方包 import ElementUI from 'element-ui' Vue.use(ElementUI) Vue.prototype.$http = http Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
二、router(路由跳转配置)
router做用
:简单理解就是帮助组件之间跳转用的。
这里为了性能都采用懒加载,还有这里无论先登录登录页面 默认跳转组件为 Main.vue
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) // 完整路由代码 export default new VueRouter({ routes: [ { path: '/', component: () => import('@/views/Main'), children: [ { path: '/', name: 'home', component: () => import('@/views/Home/Home'), }, { path: '/user', name: 'user', component: () => import('@/views/UserManage/UserManage'), }, { path: '/mall', name: 'mall', component: () => import('@/views/MallManage/MallManage'), }, { path: '/page1', name: 'page1', component: () => import('@/views/Other/PageOne'), }, { path: '/page2', name: 'page2', component: () => import('@/views/Other/PageTwo'), }, ] } ] })
三、vuex(存储共享数据)
vuex做用
:vuex解决了组件之间同一状态的共享问题。
export default { //存储数据 state: { isCollapse: false }, //调用方法 mutations: { collapseMenu(state) { state.isCollapse = !state.isCollapse } }, actions: {} }
这里先只设定一个全局数据isCollapse,用于侧边栏是否水平展开。
四、axios
axios做用
:axios主要是用于向后台发起请求的,还有在请求中作更可能是可控功能。
import axios from 'axios' // 建立一个axios实例 const service = axios.create({ // 请求超时时间 timeout: 3000 }) export default service
其它的这里就不详细讲解了,在文章最下面会附上github地址
这个是后台系统的主组件,它采用的布局是 element-ui的 Container 布局容器 Container 布局容器
<template> <el-container style="height: 100%"> <!--左侧栏--> <el-aside width="auto"> <!--左侧栏控件--> <common-aside></common-aside> </el-aside> <!--右侧栏--> <el-container> <!--header部分--> <el-header> <!--header部分控件--> <common-header></common-header> </el-header> <el-main> <!--左侧栏 和 header部分对于整个后台部分都是不变的,惟一变的就是上面3的部分,这里就经过router-view来展现所需控件--> <router-view/> </el-main> </el-container> </el-container> </template> <script> import CommonAside from '../components/CommonAside' import CommonHeader from "../components/CommonHeader"; export default { components: { CommonAside, CommonHeader } } </script>
这样整个后台管理系统的整个轮廓就定下来了,接下来经过路由的切换的组件展现在router-view
的位置。
它采用的布局是 element-ui的 NavMenu 导航菜单
<template> <!--collapse 是否水平折叠收起菜单--> <el-menu :collapse="isCollapse" :default-active="$route.path" class="el-menu-vertical-demo" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" > <!--是否水平折叠收起菜单 会影响这里字段的显示 --> <h3 v-show="isCollapse">偶囧</h3> <h3 v-show="!isCollapse">偶囧后台管理系统</h3> <el-menu-item :index="item.path" v-for="item in noChildren" :key="item.path" @click="clickMenu(item)"> <i :class="'el-icon-' + item.icon"></i> <span slot="title">{{ item.label }}</span> </el-menu-item> <el-submenu :index="item.label" v-for="(item, index) in hasChildren" :key="index"> <template slot="title"> <i :class="'el-icon-' + item.icon"></i> <span slot="title">{{ item.label }}</span> </template> <el-menu-item-group> <el-menu-item :index="subItem.path" v-for="(subItem, subIndex) in item.children" :key="subIndex" @click="clickMenu(subItem)"> <i :class="'el-icon-' + subItem.icon"></i> <span slot="title">{{ subItem.label }}</span> </el-menu-item> </el-menu-item-group> </el-submenu> </el-menu> </template> <script> export default { //计算属性 computed: { //没有子菜单 noChildren() { return this.menu.filter(item => !item.children) }, //有子菜单 (这样设置会有一个问题 就是有子菜单的 永远会在没有子菜单的下面) hasChildren() { return this.menu.filter(item => item.children) }, isCollapse() { // 这里的数据就是从vuex取得 return this.$store.state.tab.isCollapse } }, data() { return { menu: [ { 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: { //跳转路由 根据名称跳转 clickMenu(item) { this.$router.push({ name: item.name }) } } } </script>
这里经过点击那个图标来控制:左侧栏是否水平折叠收起菜单,因此这里来修改vuex中 isCollapse 数据。
它采用的布局是 element-ui的 Dropdown 下拉菜单
<template> <header> <div class="l-content"> <el-button plain icon="el-icon-menu" size="mini" @click="collapseMenu"></el-button> <h3 style=" color : #fff">首页</h3> </div> <div class="r-content"> <el-dropdown trigger="click" size="mini"> <span class="el-dropdown-link"><img :src="userImg" class="user"/></span> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>我的中心</el-dropdown-item> <el-dropdown-item @click.native="logOut">退出</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </div> </header> </template> <script> export default { data() { return { userImg: require('../assets/images/user.png') } }, methods: { //控制左侧菜单是否折叠 collapseMenu() { this.$store.commit('collapseMenu') }, //退出登录 logOut() { location.reload() } } } </script>
它采用的布局是 element-ui的 Card 卡片 + Layout 布局
<template> <el-row class="home" :gutter="20"> <!--span默认一共是24,这里占8 下面占16,因此这两个分隔栏所占的宽度 是1:2--> <el-col :span="8" style="margin-top: 20px"> <!--shadow属性设置卡片阴影出现的时机--> <el-card shadow='hover'> <div class="user"> <img :src="userImg"/> <div class="userinfo"> <p class="name">Admin</p> <p class="access">超级管理员</p> </div> </div> <div class="login-info"> <p>上次登陆时间:<span>2019-10-20</span></p> <p>上次登陆地点:<span>北京</span></p> </div> </el-card> <el-card style="height: 460px ; margin-top: 20px"> <el-table :data="tableData"> <el-table-column show-overflow-tooltip v-for="(val, key) in tableLabel" :key="key" :prop="key" :label="val"></el-table-column> </el-table> </el-card> </el-col> <el-col :span="16" style="margin-top: 20px"> <div class="num"> <el-card shadow="hover" v-for="item in countData" :key="item.name" :body-style="{ display: 'flex', padding: 0}"> <i class="icon" :class="`el-icon-${item.icon}`" :style="{ background: item.color }"></i> <div class="detail"> <p class="num">¥ {{ item.value }}</p> <p class="txt">{{ item.name }}</p> </div> </el-card> </div> <el-card shadow="hover" style="height: 280px"> </el-card> <div class="graph"> <el-card shadow="hover" style="height: 260px"> </el-card> <el-card shadow="hover" style="height: 260px"> </el-card> </div> </el-col> </el-row> </template> <script> export default { data() { return { userImg: require('../../assets/images/user.png'), countData: [], tableData: [], tableLabel: { name: '课程', todayBuy: '今日购买', monthBuy: '本月购买', totalBuy: '总购买' } } }, methods: { getTableData() { this.$http.get('/home/getData').then(res => { res = res.data this.tableData = res.data.tableData }) } }, //一进组件就会去请求后端接口 获取首页数据 created() { this.getTableData() } }
Github地址
mall-manage-system
别人骂我胖,我会生气,由于我内心认可了我胖。别人说我矮,我就会以为可笑,由于我内心知道我不可能矮。这就是咱们为何会对别人的攻击生气。 攻我盾者,乃我心里之矛(13)