用vue+elementUI+echarts做一个后台管理项目

使用vue-cli3.x的UI可视化界面创建项目

  1. vue ui

    image-20211010153348385

  2. 点击创建项目后: ( 如果你选yarn 卡住创建不了项目的话还是乖乖用npm吧 )

    image-20211010153615280

  3. 进行配置

    image-20211010153806012

  4. 选择配置: ( 练习项目, 仅选择下列几项即可, ESLint css预处理 TypeScript都是未来需要了解的 )

    • image-20211010154051573

    • image-20211010154113170

    • image-20211010154133170

    • image-20211010154151774

    • image-20211010154212842

  5. 是否使用history

    image-20211010154446711

  6. 进行创建( UI界面看不到创建进度, 需要到vscode终端下看 )

    这时可以将配置保存, 也可不保存

    image-20211010154537385

  7. vue-cli3.x的架构在 ‘仿京东实战’ 中已介绍过, 需要补充的是vue.config.js中的配置:

    // 常用配置
    module.exports = {
        //基本路径, vue-cli3.3以前请使用baseUrl
        publicPath: '/',
        //输出文件目录
        outputDir: 'dist',
        //用于嵌套生成的静态资产(js,css,img,fonts)的目录
        assetsDir: '',
        //todo 生成环境sourceMap--生成map文件,用于定位css或js哪里出错了,生成环境中一般不需要(改为false可显著减小打包体积)
        productionSourceMap: true,
        //webpack配置
        configureWebpack: () => {},
        chainWebpack: () => {},
        //css相关配置
        css: {
            //启用 CSS modules
            modules: false,
            //是否使用css分离插件
            extract: true,
            //开启 CSS source map? --用于定位错误,选为false可减小打包体积
            sourceMap: false,
            //css预设器(预处理器)配置项
            loaderOptions: {},
        },
        //webpack-dev-server 相关配置
        devServer: {
            //host: '0.0.0.0',//将服务启动在 0.0.0.0 的ip下
            port: 9528, //服务启动所在的端口
            open: true, //启动项目后自动打开浏览器
            proxy: {},//设置代理--产生跨域问题就可以在这里配置代理,这时webpack-dev-server就会在本地启动一个服务器来转发请求以解决跨域问题(服务器与服务器之间通信是没有跨域的,只有客户端和服务器间才会产生跨域)
        },
        //第三方插件配置
        pluginOptions: {
       
        }
    }
    

vue组件间传值

单页面应用控制中心vue-router

状态管理中心–vuex的基础用法(官方文档是标准)

image-20211011100716691

状态管理中心vuex的高级用法

Element常用组件—-布局组件

官网: Element - 网站快速成型工具

  1. 安装element-ui

    npm i element-ui -S
    

    -S指令就是全局安装, 在开发和生产环境上都安装

  2. 引入和挂载到全局

    //main.js
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
       
    Vue.use(ElementUI);
    
  3. 这样就可以在任何地方使用element-ui的组件了

Element常用组件—-弹出类型组件

Element常用组件—-表格组件

Element常用组件—-表单组件

项目搭建和技术选型

创建项目 vue create vue-manage-system

image-20211011163359727

image-20211011172127069

image-20211011172143308

image-20211011172214500

image-20211011172244385

image-20211011172329024

image-20211011172356931

image-20211011172446469

配置项目的基本环境及项目目录结构总体介绍

配置全局变量

后台视频管理系统之公用部分—需求分析及模块划分

image-20211021151120463

之后进入项目实战, 不在详细记录没一步的操作(没必要,也繁琐,还不一定看..), 只记录关键技术点

ElementUI全局安装并完整引入

css新单位: vh

css样式覆盖, 引入css样式时, 如果有相同的css属性被声明,那么引入在前的会覆盖引入在后的.

key

scss继承写法

.el-breadcrumb__item {
  .el-breadcrumb__inner {
    // 设置面包屑字体颜色为白色, 上面的一长串css名是直接在浏览器里看的
    color: #fff;
  }
  //scss中集成上级class名,相当于: .el-breadcrumb__item:last-child
  &:last-child {
    .el-breadcrumb__inner {
      // 设置面包屑字体颜色为白色, 上面的一长串css名是直接在浏览器里看的
      color: #fff;
    }
  }
}

elementUI调整尺寸大小的属性大多是size

在需要v-for和v-if搭配使用的场景下, 多使用v-for和计算属性来替代v-if

computed: {
    //计算属性
    noChildren() {
      //对asideMenu进行过滤,返回asideMenu数组中没有children属性的成员
      return this.asideMenu.filter((item) => !item.children)
    },
    hasChildren() {
      //对asideMenu进行过滤,返回asideMenu数组中没有children属性的成员
      return this.asideMenu.filter((item) => item.children)
    },
  },

使用vuex实现切换tab页功能

优化elementUI样式

axios全局配置

mock

布局

绑定样式

读取响应数据

table使用

echarts组件封装1

<template>
  <!-- //TODO 封装echarts组件 -->
  <!-- 之后通过ref来找到这个dom, 类似id -->
  <div style="height: 100%" ref="echart">echart</div>
</template>

<script>
import echarts from 'echarts'
export default {
  name: 'VueManageSystemEchart',
  // 数据是由父组件传来的, 所以需要接受数据
  props: {
    chartData: {
      type: Object,
      //   通过函数返回对象, 这样就避免的其他组件对我们的影响: 为什么, 如何直接设为对象, 那么当使用的时候就会产生多个此对象的引用,任何一处发生更改都会影响到其他地方
      default() {
        return {
          // x轴
          xData: [],
          //   数据--也决定了图标样式即type
          series: [],
        }
      },
    },
    // 是否有坐标轴
    isAxisChart: {
      type: Boolean,
      default: true,
    },
  },
  computed: {
    //   通过判断父组件传来的isAxisChart来决定使用哪组数据格式(有坐标轴,无坐标轴)
    options() {
      return this.isAxisChart ? this.axisOption : this.normalOption
    },
  },
  data() {
    return {
      // echart对象容器,因为官网指明了,必须先初始化一个echart对象,再将数据填入容器
      echart: null,
      //   echart大致分两种: 有坐标轴图表和无坐标轴图标
      axisOption: {},
      normalOption: {},
    }
  },

  mounted() {},

  methods: {
    //初始化图表
    initChart() {
      // 如果echart对象已经存在则直接渲染图表
      if (this.echart) {
        this.echart.setOption(this.options)
      } else {
        //   如果echart对象不存在则先初始化再渲染图表
        this.echart = echarts.init(this.$refs.echart)
        this.echart.setOption(this.options)
      }
    },
    // 处理图表数据 --依据有无坐标轴分别处理
    initChartData() {
      if (this.isAxisChart) {
        console.log('axis')
      } else {
        console.log('normal')
      }
    },
  },
}
</script>

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

echarts组件封装2

<template>
  <!-- //TODO 封装echarts组件 -->
  <!-- 之后通过ref来找到这个dom, 类似id -->
  <div style="height: 100%" ref="echart">echart</div>
</template>

<script>
//todo 引入echarts  ---注意: 引入方式和以前不一样了
import * as echarts from 'echarts'
export default {
  name: 'VueManageSystemEchart',
  // 数据是由父组件传来的, 所以需要接受数据
  props: {
    chartData: {
      type: Object,
      //   通过函数返回对象, 这样就避免的其他组件对我们的影响: 为什么, 如何直接设为对象, 那么当使用的时候就会产生多个此对象的引用,任何一处发生更改都会影响到其他地方
      default() {
        return {
          // x轴  --因为y轴数据只需要一个值,这个值来自series,所以y轴不需要额外的处理
          xData: [],
          //   数据--也决定了图标样式即type
          series: [],
        }
      },
    },
    // 是否有坐标轴
    isAxisChart: {
      type: Boolean,
      default: true,
    },
  },
  computed: {
    //   通过判断父组件传来的isAxisChart来决定使用哪组数据格式(有坐标轴,无坐标轴)
    options() {
      return this.isAxisChart ? this.axisOption : this.normalOption
    },
  },
  //   监听  --这里监听复杂数据类型,需要开启deep
  watch: {
    //   当chartData(父组件传来的)发生变化时渲染图表
    chartData: {
      handler: function () {
        this.initChart()
      },
      deep: true,
    },
  },
  data() {
    return {
      // echart对象容器,因为官网指明了,必须先初始化一个echart对象,再将数据填入容器
      echart: null,
      //   echart大致分两种: 有坐标轴图表和无坐标轴图标
      axisOption: {
        // 图例 --即图表上面内容
        legend: {
          textStyle: {
            color: '#333',
          },
        },
        // 位置偏移
        grid: {
          left: '20%',
        },
        // 悬浮提示
        tooltip: {
          // 触发时机---当鼠标在坐标轴范围内时
          trigger: 'axis',
        },
        xAxis: {
          type: 'category',
          data: [],
          //   轴线设置
          axisLine: {
            //   轴线样式
            lineStyle: {
              // 轴线颜色
              color: '#17b3a3',
            },
          },
          //   标签(文本)颜色
          axisLabel: {
            color: '#333',
          },
        },
        yAxis: {
          type: 'value',
          axisLine: {
            lineStyle: {
              color: '#17b3a3',
            },
          },
        },
        // 主题色
        color: [
          '#2ec7c9',
          '#b6a2de',
          '#5ab1ef',
          '#ffb980',
          '#d87a80',
          '#8d98b3',
          '#e5cf0d',
          '#97b552',
          '#95706d',
          '#dc69aa',
          '#07a2a4',
          '#9a7fd1',
          '#588dd5',
          '#f5994e',
          '#c05050',
          '#59678c',
          '#c9ab00',
          '#7eb00a',
          '#6f5553',
          '#c14089',
        ],
        series: [],
      },
      normalOption: {
        legend: {
          show: false,
        },
        tooltip: {
          // 触发时机---鼠标在数据项上时
          trigger: 'item',
        },
        color: ['#0f78f4', '#dd536b', '#9462e5', '#a6a6a6', '#e1bb22', '#39c362', '#3ed1cf'],
        series: [],
      },
    }
  },

  mounted() {},

  methods: {
    //初始化图表
    initChart() {
      // 渲染数据
      this.initChartData()
      // 如果echart对象已经存在则直接渲染图表
      if (this.echart) {
        this.echart.setOption(this.options)
      } else {
        //   如果echart对象不存在则先初始化再渲染图表
        this.echart = echarts.init(this.$refs.echart)
        this.echart.setOption(this.options)
      }
    },
    // 处理图表数据 --依据有无坐标轴分别处理
    initChartData() {
      //   将父组件传来的数据存进data
      if (this.isAxisChart) {
        // 使用有坐标轴的数据属性
        this.axisOption.xAxis.data = this.chartData.xData
        this.axisOption.series = this.chartData.series
      } else {
        // 使用无坐标轴的数据属性
        this.normalOption.series = this.chartData.series
      }
    },
  },
}
</script>

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

EChart组件封装总结

页面划分

image-20211101144538155

这样的底部条, 可以是一个form, 封装成我们的一个组件

image-20211101144614997

这样的表格和分页, 可以封装进一个组件

权限管理思路

权限管理之路由守卫判断用户登录状态

项目总结