VUE通用后台管理

一、vue-cli4搭建脚手架

1.安装node.js

          登录nodejs.cn下载,配置环境变量,配置过程配置过程2

           

           

2.安装cnpm

             打开npmmirror.com,在终端运行下面代码

                

npm install -g cnpm --registry=https://registry.npmmirror.com

            运行完成后,输入cnpm -v检验是否安装成功,若cnpm -v无法加载

           

            安装yarn,并检验是否安装成功

           

3.安装vue-cli脚手架构建工具

            vue-cli官方文档

cnpm install -g @vue/cli

           检验脚手架是否安装成功,vue -V

           

 4.创建项目

vue create vue-manage

       选择[Vue 2] babel, eslint,用yarn安装

        运行vue run serve

二、引入Element-ui

1.全局引入,并在main.js中引入下面两行

npm i element-ui -S
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

              将elementui注入vue,在main.js中写入

Vue.use(ElementUI)

2.打包

npm run build

3.按需引入

npm install babel-plugin-component -D
//借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。
首先,安装 babel-plugin-component

改写mian.js中import ElementUI from 'element-ui';为import {Button} from 'element-ui';

改写Vue.use(ElementUI)为Vue.use(Button)

在babel.config.js中写入

 npm i @babel/preset-env -D
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
    // ["@babel/preset-env", { "modules": false }] //有问题
  ],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

三、 vue路由的使用

vue-router官方文档

1.引入vue-router

npm i vue-router@3.2.0

2.在main.js中引入router

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
import router from './router'
//import router from '../router'

3.在根目录创建文件夹router,router内创建index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

4.根目录新建views文件夹,内新建Home.vue,User.vue

解决报错:Home报错

<template>
    <div>我是Home</div>
</template>

<script>
    export default {
        data(){
            return{}
        }
    }

</script>

5.在router中index.js

Vue.use(VueRouter)//vuerouter全局引入
import Home from '../views/Home.vue'
import User from '../views/User.vue'
import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '../views/Home.vue'
import User from '../views/User.vue'


Vue.use(VueRouter)//vuerouter全局引入
//1.创建路由组件
//2.将路由与组件进行映射

const routes = [
        {path: '/home',component:Home},//首页
        {path: '/user',component:User},//用户管理
]

6.定义一个router变量接受router实例

const router = new VueRouter({
    mode:'history',//路由匹配模式
    routes
})
//配置router

export default router
import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '../views/Home.vue'
import User from '../views/User.vue'


Vue.use(VueRouter)//vuerouter全局引入
//1.创建路由组件
//2.将路由与组件进行映射

const routes = [
        {path: '/home',component:Home},//首页
        {path: '/user',component:User},//用户管理
]

//3.创建router实例
const router = new VueRouter({
    // mode:'history',//路由匹配模式
    routes
})
//配置router

export default router

export default 是什么

  关闭eslint校验:

7.引入router组件,在App.vue(路由出口)

<router-view></router-view>

   

                                ​​​​​​     

8.点击不同按钮加载不同路由下的页面,同时进行路由切换(嵌套路由)

在views中新建Main.vue主页面,并在index.js中引入

<template>
    <div>
        <h1>main</h1>
        <router-view></router-view>
    </div>
</template>

<script>
    export default {
        data(){
            return{}
        }
    }

</script>
import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '../views/Home.vue'
import User from '../views/User.vue'
import Main from '../views/Main.vue'
const routes = [
    //主路由
    {
        path:'/',
        component:Main,
        children:[
            //子路由
            {path: '/home',component:Home},//首页
            {path: '/user',component:User},//用户管理
        ]
    },
       
]

四、ui搭建

1.首页ui搭建

引用element-ui的container布局(记得在main.js中引入局部element-ui组件)

安装less样式

npm i less
npm i less-loader@5.0.0 --legacy-peer-deps

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>

<script>
    export default {
        data(){
            return{}
        }
    }

</script>

 2.左侧菜单栏的引入

引入element-ui的NavMenu导航菜单,到component中新建CommonAside.vue(侧边栏组件)

在主页Main.vue中引入CommonAside组件

<script>
import CommonAside from '../components/CommonAside.vue'
    export default {
        data(){
            return{}
        },
        components:{
            CommonAside
        }
    }

</script>
 <el-aside width="200px">
                <common-aside />
 </el-aside>

                        

 3.一级菜单的实现

CommonAside组件中实现可展开

 return {
          isCollapse: false
        };

 将导航二移到顶部,删除导航三、四

 只保留导航二、导航一和导航一下面的选项一

对内容进行渲染,在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'
                    }
                ]
                }
            ],

过滤数据 

 computed:{
        //没有子菜单
          noChildren() {
            return this.menuData.filter(item => !item.children)
          },
        //有子菜单
          hasChildren() {
            return this.menuData.filter(item => item.children)
          }
      }

 引入icon图标

 <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>

noChildren效果图:

                                

  4.二级菜单的实现(haschildren)

<el-submenu v-for="item in hasChildren" :key="item.label" :index="item.label">
            <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.path">
            <el-menu-item :index="subItem.path">{{subItem.label}}</el-menu-item>
            </el-menu-item-group>  
</el-submenu>

                                

 5.菜单样式与less引入

安装less,less-loader

npm i less@4.1.2
npm i less-loader@6.0.0

 在component文件下的CommonAside.vue中

<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"
>

 

 引入less部分

<style lang="less" scoped>
  .el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
  }
  .el-menu{
    height: 100vh;
    h3 {
      color: #fff;
    }
  }
</style>
<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 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.label" :index="item.label">
            <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.path">
            <el-menu-item :index="subItem.path">{{subItem.label}}</el-menu-item>
            </el-menu-item-group>  
        </el-submenu>
        </el-menu>
</template>

                        ​

去白边:在App.vue中的style标签

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

</style>

 ​

 更改<h3>标签中“通用后台管理系统”样式:

 在CommonAside.vue中style的h3中

h3{
        color: #fff;
        text-align: center;
        line-height: 48px;
        font-size: 16px;
        font-weight: 400;
      }

在App.vue中的style的html,body中

html,body,h3{
  margin: 0;
  padding: 0
}

 五、菜单点击跳转功能实现(配置路由跳转)

在views中新建Mall.vue,PageOne.vue,PageTwo.vue

在router的index.js中引入

import Mall from '../views/Mall.vue'
import PageOne from '../views/PageOne.vue'
import PageTwo from '../views/PageTwo.vue'
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
        ]
    },
       
]

 实现点击跳转:

添加@click事件

 <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>

在methods中加入click事件

 //点击菜单
      clickMenu(item){
          console.log(item)
          this.$router.push(item.path)
      }

由于在main.js中挂载了router到vue实例上,所以可以使用$router属性,然后调用本身的push方法

 

存在问题:

点击首页跳转的是 ‘/’ ,原因是在当前路径再点击跳转当前路径会报错

 解决:

在route的index.js中,加入重定向,意思是当路径是‘/’的时候重定向到‘/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
        ]
    },
       
]

 

二级菜单的跳转:

<el-submenu v-for="item in hasChildren" :key="item.label" :index="item.label">
            <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.path">
            <el-menu-item @click="clickMenu(subItem)" :index="subItem.path">            
            {{subItem.label}}</el-menu-item>
            </el-menu-item-group>  
</el-submenu>

解决重复点击报错问题:

 //点击菜单
      clickMenu(item){
          console.log(item)
          //当页面路由与跳转的路由不一致才允许跳转
        if(this.$route.path !== item.path && !(this.$route.path === '/home' && (item.path                 
              === '/')))
          {this.$router.push(item.path)} 
          //$route表示当前页面路由,$router表示整个router实例
      }

点击首页三次

 六、header组件搭建与样式调整

header边框:

在component里新建CommonHeader.vue

<template>
    <div class="header-container">
        <div class="l-content"></div>
        <div class="r-content"></div>
    </div>
</template>

<script>
    export default {
        data(){
            return{}
        }
    }

</script>
<style lang="less" scoped>
.header-container {
    background-color: #333;
    height: 60px;
}
</style>

在Main.vue中引入CommonHeader.vue组件

<script>
import CommonAside from '../components/CommonAside.vue'
import CommonHeader from '../components/CommonHeader.vue'
    export default {
        data(){
            return{}
        },
        components:{
            CommonAside,
            CommonHeader
        }
    }

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

 

去掉padding

在Main.vue中加入

<style scoped>
.el-header {
    padding: 0
}
</style>

顶部左侧: 

引入element-ui的icon

 在CommonHeader.vue中

<style lang="less" scoped>
.header-container {
    padding: 0 20px;
    background-color: #333;
    height: 60px;
    display:flex;
    justify-content:space-between;
    align-items: center;
}
</style>
<template>
    <div class="header-container">
        <div class="l-content">
            <el-button icon="el-icon-menu" size="mini"></el-button>
        </div>
        <div class="r-content"></div>
    </div>
</template>

 面包屑

<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"></div>
    </div>
</template>
<style lang="less" scoped>
.header-container {
    padding: 0 20px;
    background-color: #333;
    height: 60px;
    display:flex;
    justify-content:space-between;
    align-items: center;
    .text{
        color:#fff;
        font-size:14px;
        margin-left: 10px;
    }
}
</style>

                

顶部右侧:

引入element-ui的dropdown组件

<el-dropdown>
                <span class="el-dropdown-link">
                   <img class="user" src="../assets/images/user.png">
                </span>
                <el-dropdown-menu slot="dropdown">
                    <el-dropdown-item>个人中心</el-dropdown-item>
                    <el-dropdown-item>退出</el-dropdown-item>
                </el-dropdown-menu>
</el-dropdown>

<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 class="user" src="../assets/images/user.png">
                </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>

在 .header-container 中写入样式

.r-content{
        .user{
            width:40px;
            height:40px;
            border-radius:50%;
        }
    }

七、vuex实现左侧折叠

vuex是什么

npm i vuex@3.6.2

在src下新建文件夹store,store下新建index.js,tab.js(管理菜单相关数据),

之前的isCollapse定义在字段内部(return)下

index.js中

import Vue from 'vue'
import Vuex from 'vuex'
import tab from './tab'

Vue.use(Vuex)

//创建vuex的实例,并对外暴露
export default new Vuex.Store(
    {
        modules:{
            tab
        }
    }
)

tab.js中

export default {
    state:{
        isCollapse:false //控制菜单的展开还是收起
    },
    mutations: {
        //修改菜单展开收起的方法
        collapseMenu(state) {
            state.isCollapse = !state.isCollapse
        }
    }
}

store实例挂载到vue实例中,需要在main.js中引入

import store from './store'
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

第一步,在CommonHeader.vue中获取mutations方法

 <el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>

通过commit方法调用对应的mutations 

<script>
    export default {
        data(){
            return{}
        },
       methods: {
        handleMenu(){
            this.$store.commit('collapseMenu')
        }
       }
    }

</script>

第二步,在CommonAside.vue中获取store

在computed属性下写入(删除之前定义在data中的isCollapse)

 isCollapse() {
            return this.$store.state.tab.isCollapse
          }

 解决左侧展开显示问题:

在CommonAside.vue中

<h3>{{isCollapse ? '后台': '通用后台管理系统' }}</h3>

在Main.vue中,将width="200px"改为auto

<el-aside width="auto">
                <common-aside />
</el-aside>

 

去掉缝隙,在 CommonAside.vue中,加入style

<style lang="less" scoped>
.el-menu {
  border-right: none;
}
</style>

 八、home组件布局

使用layout布局

 使用card卡片,实现阴影效果

 在Home.vue中,使用layout布局并加入一个card

<template>
    <el-row>
     <el-col :span="8">
        <el-card class="box-card">
            <div class="user">
                <img src="../assets/images/user.png" alt="">
                <div class="userinfo">
                    <p class="name">Admin</p>
                    <p class="access">超级管理员</p>
                </div>
            </div>
            <div class="login-info">
                <p>上次登陆时间:<span>2021-7-19</span></p>
                <p>上次登陆地点:<span>武汉</span></p>
            </div>
        </el-card>
    </el-col>
    <el-col :span="16"><div class="grid-content bg-purple-light"></div></el-col>
    </el-row>
</template>
<style lang="less" scoped>
.user {
    padding-bottom:20px;
    margin-bottom: 20px;
    border-bottom: 1px solid #ccc;
    display: flex;
    align-items: center;
    img { 
        margin-right: 40px;
        width:150px;
        height: 150px;
        border-radius: 50%;
    }
    .userinfo {
      
        .name {
            font-size: 32px;
            margin-bottom: 10px;
        }
        .access {
            color:#999999;
        }
    }
}
.login-info {
    p {
            line-height: 28px;
            font-size: 14px;
            color:#999999;
            span {
                color:#666666;
                margin-left: 10px;
            }
        }
}
</style>

九、home购买统计部份

 

在Home.vue中第二个<el-card>中引入<el-table> 

<el-card>
            <el-table
            :data="tableData"
             style="width: 100%">
              <el-table-column
                prop="name"
                label="课程"
                width="180">
              </el-table-column>
              <el-table-column
                prop="todayBuy"
                label="今日购买"
                width="180">
              </el-table-column>
              <el-table-column
                prop="monthBuy"
                label="本月购买"
                width="180">
              </el-table-column>
              <el-table-column
                prop="totalBuy"
                label="总购买"
                width="180">
              </el-table-column>
            </el-table>
</el-card>

并在return中写入

tableData: [
                        {
                            name: 'oppo',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: 'vivo',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '苹果',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '小米',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '三星',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '魅族',
                        todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        }
          ]

加入样式:

<el-card style="margin-top:20px;height:460px;">
            <el-table
            :data="tableData"
             style="width: 100%">
              <el-table-column
                prop="name"
                label="课程">
              </el-table-column>
              <el-table-column
                prop="todayBuy"
                label="今日购买">
              </el-table-column>
              <el-table-column
                prop="monthBuy"
                label="本月购买">
              </el-table-column>
              <el-table-column
                prop="totalBuy"
                label="总购买">
              </el-table-column>
            </el-table>
</el-card>

 

 简化代码:

在return中写入tableLabel

 export default {
        data(){
            return{
                tableData: [
                        {
                            name: 'oppo',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: 'vivo',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '苹果',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '小米',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '三星',
                            todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        },
                        {
                            name: '魅族',
                        todayBuy: 100,
                            monthBuy: 300,
                            totalBuy: 800
                        }
                        ],
                tableLabel:{
                    name: '课程',
                    todayBuy: '今日购买',
                    monthBuy: '本月购买',
                    totalBuy: '总购买',
                }
            }
        }
    }

注释掉之前的 用v-for动态循环遍历tableLabel

<el-card style="margin-top:20px;height:460px;">
            <el-table
            :data="tableData"
             style="width: 100%">
              <!-- <el-table-column
                prop="name"
                label="课程">
              </el-table-column>
              <el-table-column
                prop="todayBuy"
                label="今日购买">
              </el-table-column>
              <el-table-column
                prop="monthBuy"
                label="本月购买">
              </el-table-column>
              <el-table-column
                prop="totalBuy"
                label="总购买">
              </el-table-column> -->
              <el-table-column v-for="(val,key) in tableLabel" :prop="key" :label="val" />
            </el-table>
</el-card>

十、home订单统计实现

导入订单数据:

 将数据渲染到页面右侧:

<el-col :span="16">
        <div class="num">
            <el-card v-for="item in countData" :key="item.name">
                <i class="icon" :class="`el-icon-${item.icon}`"></i>
            </el-card>
        </div>
</el-col>

使用icon图标

 渲染文字:

<el-col :span="16">
        <div class="num">
            <el-card v-for="item in countData" :key="item.name">
                <i class="icon" :class="`el-icon-${item.icon}`"></i>
                <div>
                    <p>{{ item.value }}</p>
                    <p>{{ item.name }}</p>
                </div>
            </el-card>
        </div>
</el-col>

 调整<el-card>样式,实现左右布局:

 添加icon样式:

.num{
    .icon{
        width:80px;
        height:80px;
        font-size:30px;
        text-align:center;
        line-height:80px;
        color:#fff;
    }
}

加入icon颜色:

 

 调整文字,垂直居中:

.detail{
    display:flex;
    flex-direction:column;
    justify-content: center;
}

 调整文字样式:

.detail{
    margin-left: 15px;
    display:flex;
    flex-direction:column;
    justify-content: center;
    .price{
        font-size: 30px;
        margin-bottom: 10px;
        line-height: 30px;
        height: 30px;
    }
    .desc{
        font-size: 14px;
        color: #999;
        text-align: center;
    }
}

调整布局:

 display:flex

flex:wrap 自动换行:

 .el-card{
        width:32%;
        margin-bottom: 20px;
    }

 

调整边距:

 

十一、axios的基本使用和二次封装

axios文档

npm install axios

封装axios,创建实例:

在src下新建文件夹utils中新建文件request.js

import axios from 'axios'

const http = axios.create({
    //通用请求地址前缀
    baseURL:'/api',
    timeout:10000,//超时时间
})

export default http 

添加拦截器:

import axios from 'axios'

const http = axios.create({
    //通用请求地址前缀
    baseURL:'/api',
    timeout:10000,//超时时间
})

// 添加请求拦截器,绑定http实例
http.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器,绑定http实例
http.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

export default http 

创建接口:

在src下新建文件夹api中新建index.js

import http from '../utils/request'

//请求首页数据
export const getData = () => {
    //返回一个promise对象
    return http.get('/home/getData')
}

调用接口:

在Home.vue中

 调用成功

十二、mock数模拟实战

mock文档,用来前端模拟后端接口

# 安装
npm install mockjs

在api下新建mock.js

import Mock from 'mockjs'

//定义mock请求拦截
Mock.mock('/api/home/getData',function(){
    //拦截到请求后的处理逻辑
    console.log('拦截到了')
})

 在main.js中引入

import './api/mock'

拦截到了 

 在mock中return 1

 封装mock:

在api下新建文件夹mockServeData,中新建home.js和permission.js

在home.js中写入

// mock数据模拟
import Mock from 'mockjs'

// 图表数据
let List = []
export default {
  getStatisticalData: () => {
    //Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位
    for (let i = 0; i < 7; i++) {
      List.push(
        Mock.mock({
          苹果: Mock.Random.float(100, 8000, 0, 0),
          vivo: Mock.Random.float(100, 8000, 0, 0),
          oppo: Mock.Random.float(100, 8000, 0, 0),
          魅族: Mock.Random.float(100, 8000, 0, 0),
          三星: Mock.Random.float(100, 8000, 0, 0),
          小米: Mock.Random.float(100, 8000, 0, 0)
        })
      )
    }
    return {
      code: 20000,
      data: {
        // 饼图
        videoData: [
          {
            name: '小米',
            value: 2999
          },
          {
            name: '苹果',
            value: 5999
          },
          {
            name: 'vivo',
            value: 1500
          },
          {
            name: 'oppo',
            value: 1999
          },
          {
            name: '魅族',
            value: 2200
          },
          {
            name: '三星',
            value: 4500
          }
        ],
        // 柱状图
        userData: [
          {
            date: '周一',
            new: 5,
            active: 200
          },
          {
            date: '周二',
            new: 10,
            active: 500
          },
          {
            date: '周三',
            new: 12,
            active: 550
          },
          {
            date: '周四',
            new: 60,
            active: 800
          },
          {
            date: '周五',
            new: 65,
            active: 550
          },
          {
            date: '周六',
            new: 53,
            active: 770
          },
          {
            date: '周日',
            new: 33,
            active: 170
          }
        ],
        // 折线图
        orderData: {
          date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
          data: List
        },
        tableData: [
          {
            name: 'oppo',
            todayBuy: 500,
            monthBuy: 3500,
            totalBuy: 22000
          },
          {
            name: 'vivo',
            todayBuy: 300,
            monthBuy: 2200,
            totalBuy: 24000
          },
          {
            name: '苹果',
            todayBuy: 800,
            monthBuy: 4500,
            totalBuy: 65000
          },
          {
            name: '小米',
            todayBuy: 1200,
            monthBuy: 6500,
            totalBuy: 45000
          },
          {
            name: '三星',
            todayBuy: 300,
            monthBuy: 2000,
            totalBuy: 34000
          },
          {
            name: '魅族',
            todayBuy: 350,
            monthBuy: 3000,
            totalBuy: 22000
          }
        ]
      }
    }
  }
}

在mock.js中调用

import Mock from 'mockjs'
import homeApi from './mockServeData/home'

//定义mock请求拦截
Mock.mock('/api/home/getData', homeApi.getStatisticalData)

十三、首页可视化图表样式调整

 解构赋值运用到函数参数

在Home.vue中

 mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(tableData)
            })
        }

打印成功

 删除tableData中写死的数据

  mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                this.tableData = tableData
            })
        }

调整样式:

 左右各加10px

  <el-card style="height:280px">
            <!-- 折线图 -->
  </el-card>
  <div class="graph">
            <el-card style="height:260px"></el-card>
            <el-card style="height:260px"></el-card>
  </div>

 

.graph{
    margin-top: 20px;
    display: flex;
    justify-content: space-between;
    .el-card{
        width:48%;
    }
}

十四、echarts表格的折线图

npm i echarts@5.1.2

在Home.vue中引入echarts

import * as echarts from 'echarts'

初始化echarts实例

        mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(data)
                this.tableData = tableData

                // 基于准备好的dom,初始化echarts实例
                const echarts1 = echarts.init(this.$refs.echarts1)
                // 指定图表的配置项和数据
                 var option = {}
                 //处理数据xAxis
                const { orderData } = data.data
                const xAxis = Object.keys(orderData.data[0])
                console.log(xAxis)
                })
            

        }

打印x轴数据 

 处理数据:

        mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(data)
                this.tableData = tableData

                // 基于准备好的dom,初始化echarts实例
                const echarts1 = echarts.init(this.$refs.echarts1)
                // 指定图表的配置项和数据
                 var echarts1Option = {}
                 //处理数据xAxis
                const { orderData } = data.data
                const xAxis = Object.keys(orderData.data[0])
                echarts1Option.xAxis = xAxis
                echarts1Option.legend = {
                    data:xAxis
                }
                echarts1Option.series = []
                xAxis.forEach(key => {
                    echarts1Option.series.push({
                        name:key,
                        data:orderData.data.map(item => item[key]),
                        type:'line'
                    })
                    console.log(echarts1Option)
                })
                
                console.log(xAxis)
                })
            

        }

显示折线图

        mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(data)
                this.tableData = tableData

                // 基于准备好的dom,初始化echarts实例
                const echarts1 = echarts.init(this.$refs.echarts1)
                // 指定图表的配置项和数据
                 var echarts1Option = {}
                 //处理数据xAxis
                const { orderData } = data.data
                const xAxis = Object.keys(orderData.data[0])
                const xAxisData = {
                    data:xAxis
                }
                echarts1Option.xAxis = xAxisData
                echarts1Option.yAxis = {}
                echarts1Option.legend = xAxisData
                echarts1Option.series = []
                xAxis.forEach(key => {
                    echarts1Option.series.push({
                        name:key,
                        data:orderData.data.map(item => item[key]),
                        type:'line'
                    })
                    console.log(echarts1Option)
                    // 使用刚指定的配置项和数据显示图表。
                    echarts1.setOption(echarts1Option)
                })
                
                console.log(xAxis)
                })
            

        }

 

 十五、echarts表格的柱状图

   mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(data)
                this.tableData = tableData

                // 基于准备好的dom,初始化echarts实例
                const echarts1 = echarts.init(this.$refs.echarts1)
                // 指定图表的配置项和数据
                 var echarts1Option = {}
                 //处理数据xAxis
                const { orderData,userData } = data.data
                const xAxis = Object.keys(orderData.data[0])
                const xAxisData = {
                    data:xAxis
                }
                echarts1Option.xAxis = xAxisData
                echarts1Option.yAxis = {}
                echarts1Option.legend = xAxisData
                echarts1Option.series = []
                xAxis.forEach(key => {
                    echarts1Option.series.push({
                        name:key,
                        data:orderData.data.map(item => item[key]),
                        type:'line'
                    })
                    console.log(echarts1Option)
                    // 使用刚指定的配置项和数据显示图表。
                    echarts1.setOption(echarts1Option)

                    //柱状图
                   // 基于准备好的dom,初始化echarts实例
                    const echarts2 = echarts.init(this.$refs.echarts2)
                    // 指定图表的配置项和数据
                    const echarts2Option =  {
                            legend: {
                                // 图例文字颜色
                                textStyle: {
                                color: "#333",
                                },
                            },
                            grid: {
                                left: "20%",
                            },
                            // 提示框
                            tooltip: {
                                trigger: "axis",
                            },
                            xAxis: {
                                type: "category", // 类目轴
                                data: userData.map(item =>item.date),
                                axisLine: {
                                lineStyle: {
                                    color: "#17b3a3",
                                },
                                },
                                axisLabel: {
                                interval: 0,
                                color: "#333",
                                },
                            },
                            yAxis: [
                                {
                                type: "value",
                                axisLine: {
                                    lineStyle: {
                                    color: "#17b3a3",
                                    },
                                },
                                },
                            ],
                            color: ["#2ec7c9", "#b6a2de"],
                            series: [
                                {
                                    name:'新增用户',
                                    data:userData.map(item =>item.new),
                                    type:'bar'
                                },
                                {
                                    name:'活跃用户',
                                    data:userData.map(item =>item.active),
                                    type:'bar'
                                }
                            ],
                            }
                    
                    echarts2.setOption(echarts2Option)


                })
                
             
                })
            

        }

十六、echarts表格的饼状图

 

   mounted(){
            getData().then(({data}) => {
                const { tableData } = data.data
                console.log(data)
                this.tableData = tableData

                // 基于准备好的dom,初始化echarts实例
                const echarts1 = echarts.init(this.$refs.echarts1)
                // 指定图表的配置项和数据
                 var echarts1Option = {}
                 //处理数据xAxis
                const { orderData,userData,videoData } = data.data
                const xAxis = Object.keys(orderData.data[0])
                const xAxisData = {
                    data:xAxis
                }
                echarts1Option.xAxis = xAxisData
                echarts1Option.yAxis = {}
                echarts1Option.legend = xAxisData
                echarts1Option.series = []
                xAxis.forEach(key => {
                    echarts1Option.series.push({
                        name:key,
                        data:orderData.data.map(item => item[key]),
                        type:'line'
                    })
                    console.log(echarts1Option)
                    // 使用刚指定的配置项和数据显示图表。
                    echarts1.setOption(echarts1Option)

                    //柱状图
                   // 基于准备好的dom,初始化echarts实例
                    const echarts2 = echarts.init(this.$refs.echarts2)
                    // 指定图表的配置项和数据
                    const echarts2Option =  {
                            legend: {
                                // 图例文字颜色
                                textStyle: {
                                color: "#333",
                                },
                            },
                            grid: {
                                left: "20%",
                            },
                            // 提示框
                            tooltip: {
                                trigger: "axis",
                            },
                            xAxis: {
                                type: "category", // 类目轴
                                data: userData.map(item =>item.date),
                                axisLine: {
                                lineStyle: {
                                    color: "#17b3a3",
                                },
                                },
                                axisLabel: {
                                interval: 0,
                                color: "#333",
                                },
                            },
                            yAxis: [
                                {
                                type: "value",
                                axisLine: {
                                    lineStyle: {
                                    color: "#17b3a3",
                                    },
                                },
                                },
                            ],
                            color: ["#2ec7c9", "#b6a2de"],
                            series: [
                                {
                                    name:'新增用户',
                                    data:userData.map(item =>item.new),
                                    type:'bar'
                                },
                                {
                                    name:'活跃用户',
                                    data:userData.map(item =>item.active),
                                    type:'bar'
                                }
                            ],
                            }
                    
                    echarts2.setOption(echarts2Option)


                    //饼状图
                    // 基于准备好的dom,初始化echarts实例
                    const echarts3 = echarts.init(this.$refs.echarts3)
                    // 指定图表的配置项和数据
                     const echarts3Option = {
                        tooltip: {
                            trigger: "item",
                        },
                        color: [
                            "#0f78f4",
                            "#dd536b",
                            "#9462e5",
                            "#a6a6a6",
                            "#e1bb22",
                            "#39c362",
                            "#3ed1cf",
                        ],
                        series: [
                            {
                                data:videoData,
                                type:'pie'
                            }

                        ],
                        }
                        echarts3.setOption(echarts3Option)



                })
                
             
                })
            

        }

十七、面包屑数据处理

在components中的CommonHeader.vue中,引入面包屑

 

<div class="l-content">
            <el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>
            <!-- 面包屑 -->
            <el-breadcrumb separator="/">
                <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
                <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
                <el-breadcrumb-item>活动列表</el-breadcrumb-item>
                <el-breadcrumb-item>活动详情</el-breadcrumb-item>
            </el-breadcrumb>
</div>

 定义数据部分:

在store的tab.js中

  state:{
        isCollapse:false ,//控制菜单的展开还是收起
        tabsList: [
            {
                path: '/',
                name: 'home',
                label: '首页',
                icon: 's-home',
                url: 'Home/Home'
            }
        ]//面包屑的数据
    },
    mutations: {
        //修改菜单展开收起的方法
        collapseMenu(state) {
            state.isCollapse = !state.isCollapse
        },
        //更新面包屑数据
        selectMenu(state,val){
            console.log(val,'val')

        }
    }

在CommonAside中,调用mutations

 

更新数据:

在tab.js中

    mutations: {
        //修改菜单展开收起的方法
        collapseMenu(state) {
            state.isCollapse = !state.isCollapse
        },
        //更新面包屑数据
        selectMenu(state,val){
            console.log(val,'val')
            //判断添加的数据是否为首页
            if(val.name !== 'home'){
                const index = state.tabsList.findIndex(item => item.name === val.name)
                //如果不存在
                if(index === -1){
                    state.tabsList.push(val)
                }
            }

        }
    }

 使用:

在CommonHeader.vue中

<script>
import { mapState } from 'vuex'
    export default {
        data(){
            return{}
        },
       methods: {
        handleMenu(){
            this.$store.commit('collapseMenu')
        }
       },
       computed:{
        ...mapState({
            tags:state => state.tab.tabsList
        })
       },
       mounted(){
        console.log(this.tabs,'tags')
       }
    }

</script>

页面渲染:

<div class="l-content">
            <el-button @click="handleMenu" icon="el-icon-menu" size="mini"></el-button>
            <!-- 面包屑 -->
            <el-breadcrumb separator="/">
                <el-breadcrumb-item v-for="item in tags" :key="item.path" :to="{ path:             
             item.path }">{{item.label}}</el-breadcrumb-item>
            </el-breadcrumb>
</div>

 

添加样式在CommonHeader中:

.l-content {
        display: flex;
        align-items: center;
        /deep/.el-breadcrumb__item{
            .el-breadcrumb__inner {
                font-weight:normal;
                &.is-link {
                    color:#666
                }
            }
            &:last-child {
                .el-breadcrumb__inner{
                    color: #fff;
                }
            }
        }
    }

 

十八、tag功能介绍&页面编写

 在components中新建CommonTag.vue

<template>
    <div class="tabs">
        <el-tag
            v-for="item in tags"
            :key="item.path"
            :closable="item.name !== 'home'"
            :effect="$route.name === item.name ? 'dark' : 'plain'">
            {{ item.label }}
        </el-tag>
    </div>
</template>
<script>
import { mapState } from 'vuex'
export default {
    name:'CommonTag',
    data() {
        return {}
    },
    computed:{
        ...mapState({
            tags:state => state.tab.tabsList
        })
    }
}
</script>

在Main.vue中引入CommonTag.vue

在router中的index.js中加入‘name’

十九、tag点击与删除事件

点击tag跳转:

 methods:{
        //点击tag跳转的功能
        changeMenu(item){
            // console.log(item)
            this.$router.push({name:item.name})
        }
    }

 

点击删除:

    methods:{
        ...mapMutations(['closeTag']),
        //点击tag跳转的功能
        changeMenu(item){
            // console.log(item)
            this.$router.push({name:item.name})
        },
        //点击tag删除的功能
        handleClose(item,index){
            //调用store中的mutations
            this.closeTag(item)
            const length = this.tags.length - 1
        }
    }

在tab.js中 

点×有数据

只删除(还未跳转):

 //删除指定的tag数据
        closeTag(state,item){
            // console.log(item,'item')
            const index = state.tabsList.findIndex(val => val.name === item.name)
            state.tabsList.splice(index,1)
        }

 

删除并跳转:

 在CommonTag.vue中

   //点击tag删除的功能
        handleClose(item,index){
            //调用store中的mutations
            this.closeTag(item)
            const length = this.tags.length 
            //删除之后的跳转
            if (item.name !== this.$route.name) {
                return 
            }
            //表示的是删除的最后一项
            if(index === length) {
                this.$router.push({
                    name:this.tags[index - 1].name
                })
            }
            else{
                this.$router.push({
                    name:this.tags[index].name
                })
            }

        }

添加样式

<style lang="less" scoped>
.tabs{
    padding: 20px;
    .el-tag{
        margin-right:15px;
        cursor:pointer;
    }
}
</style>

 

 

 删除最后一个:

删除中间:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值