0


VUE2+Element-ui+封装Echarts图表

VUE2+Element-ui+Echarts图表

封装Echarts图表,如下效果图

请添加图片描述

Home组件代码块,使用的mock.js模拟数据封装
<template>
  <div style="height: 400px">
    <ChartsPart id="demo" :chartData="echartData.order"></ChartsPart>
  </div>
</template>
 
<script>
//引入组件 略去
import ChartsPart from '@/components/EchartEasy.vue'
export default {
  components: {
    ChartsPart,
  },

  data() {
    return {
      echartData: {
        // 订单折线图数据
        order: {
          // X轴数据
          xData: [],
          yData: {
            type: 'value',
          },
          // series是x轴图表内,一个个的数据坐标轴
          series: [],
        },
        // 用户柱状图数据
        user: {
          xData: [],
          // series是x轴图表内,一个个的数据坐标轴
          series: [],
        },
        // 视频饼状图数据
        video: {
          // series是x轴图表内,一个个的数据坐标轴
          series: [],
        },
      },
    }
  },
  methods: {
    getTableData() {
      this.$http.get('/home/getOnData').then((res) => {
        // EChart图表数据
        res = res.data
        // console.log(res.data)
        // 订单折线图
        const order = res.data.orderData
        // console.log(order)
        // x轴数据
        this.echartData.order.xData = order.date
        // series图像渲染,x轴中的内置图表
        // 第一步取出series中name部分-键名
        // 通过 对象中的键值取出,需要数据的键名
        let keyArray = Object.keys(order.data[0])
        console.log(keyArray)
        // 循环遍历每一项数据
        keyArray.forEach((key) => {
          // 在data数据中定义的echartData.order.series中存放数据
          this.echartData.order.series.push({
            name: key === 'wechat' ? '小程序' : key,
            // key是一个变量,所以要[在这里装着],变量提升
            data: order.data.map((item) => item[key]),
            type: 'line', // 线性图
          })
        })
      })
    },
  },
  // 页面还没渲染完成,在这里调用接口比较好
  created() {
    // console.log(this.echartData.order)
    // console.log(this.ChartTestData)
    this.getTableData()
  },
}
</script>

Echarts图表组件

<template>
  <div style="height: 400px" ref="myEchart">echart</div>
</template>
 
<script>
import * as echarts from 'echarts'
export default {
  name: 'EchartEasy',
  // 数据部分是由,父组件传入的
  props: {
    chartData: {
      // 数据肯定是一个对象
      type: Object,
      // 设置对象的默认值
      // 使用default函数,再return返回
      // 父组件修改内容,本身组件不受影响
      default() {
        return {
          // x轴的数据
          xData: [],
          yData: {
            type: 'value',
          },
          // y轴的值,是根据x轴中图表的数据进行动态增加或减少的
          // yAxis: {
          //   type: 'value',
          // },
          // y轴的值,是根据x轴中图表的数据进行动态增加或减少的
          // series是x轴图表内,一个个的数据坐标轴
          series: [],
        }
      },
    },
    // 判断数据是否,带坐标轴的数据,进行渲染
    isAxisChart: {
      type: Boolean,
      // 大部分数据是有坐标轴的,例如:折线图,柱形图;(饼状图是没有坐标轴的)
      default: true,
    },
  },
  data() {
    return {
      // 用于判断容器是否存在
      offChart: null,
      // 有坐标轴的配置
      axisOption: {
        // X轴数据渲染
        xAxis: {
          // 类目轴
          type: 'category',
          data: [],
        },
        // Y轴数据渲染
        yAxis: [
          {
            // 连续的数据,根据x轴中series图表数据,动态改变
            type: 'vlaue',
          },
        ],
        // 根据series渲染成(折线,住状图等)
        series: [],
      },
      // 没有有坐标轴的配置
      normalOption: {
        // 例如饼状图,没有x轴或y轴,只需要一个series就足够了
        // 根据series渲染成(折线,住状图等)
        series: [],
      },
    }
  },
  // 计算属性
  // 根据isAxisChart来判断,选择那个图表 axisOption 或 normalOption
  computed: {
    // 最终要去使用的options数据
    options() {
      return this.isAxisChart ? this.axisOption : this.normalOption
    },
  },
  // 监听属性
  watch: {
    // chartData数据发生变化的时候监听, 对象要使用深度监听
    chartData: {
      // 如果发生变化
      handler(newVal, oldVal) {
        if (this.chart) {
          // 使用echarts图表渲染新数据
          this.chart.setOption(newVal)
        } else {
          // 调用Echarts图表渲染
          this.initChart()
        }
      },
      deep: true,
    },
  },

  methods: {
    initChart() {
      // 在初始化图表的时候,先渲染图表数据
      this.initChartData()
      // 如果容器不存在
      if (this.offChart) {
        // setOption 使用刚指定的配置项和数据显示图表
        // this.options 对应的是computed计算属性中的options
        this.offChart.setOption(this.options)
        console.log('容器不存在')
      } else {
        // 如果容器存在,init 初始化这个对象(通过ref的方法获取到这个dom)
        this.offChart = echarts.init(this.$refs.myEchart)
        this.offChart.setOption(this.options)
      }
    },
    // 配置图表数据
    initChartData() {
      // 根据数据类型,判断渲染那种图表,例如折线图,或饼状图
      // 如果是带坐标轴的图表
      if (this.isAxisChart) {
        // 折线图,x轴底部数据等于,父组件传入的数据
        this.axisOption.xAxis.data = this.chartData.xData
        // x轴中内置图表等于,父组件传入的数据
        this.axisOption.yAxis = this.chartData.yData
        this.axisOption.series = this.chartData.series
        console.log('带坐标轴的数据')
        console.log(this.chartData)
        //
      } else {
        // 不带坐标轴的图表
        console.log('normalOption不带坐标轴的数据')
      }
    },
  },
}
</script>

安装所需依赖

cnpm i axios -S 安装axios接口请求
cnpm i mockjs 或 yarn add mockjs 安装mockjs生成模拟随机数据
cnpm i echarts 或 yarn add echarts 安装echarts图表
cnpm i element-ui -S 安装element-ui组件库

安装less
cnpm install less less-loader --sav-dev
cnpm i style-resources-loader --save
cnpm i vue-cli-plugin-style-resources-loader --save

vue.config.js配置如下
const { defineConfig } = require('@vue/cli-service')
const path = require('path')
module.exports = defineConfig({
  lintOnSave: false,
  transpileDependencies: true,
  // 自动打开浏览器
  devServer: {
    // 端口号
    port: 8888,
    // 运行项目自动打开浏览器
    open: true,
  },
  // 添加全局less变量
  pluginOptions: {
    'style-resources-loader': {
      preProcessor: 'less',
      patterns: [
        // 路径
        path.resolve(__dirname, './src/assets/less/_variable.less'),
        // _variable.less文件中 @theme-color:#33aef0;(测试less是否正常使用)
      ],
    },
  },
})

在main.js中全局引入mock


import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

// 全局配置 全局初始化css样式
import http from '@/axios/api/config'
import 'element-ui/lib/theme-chalk/index.css'
import './assets/less/reset.less'
import './mock' //引入mock虚拟数据

// 使用 第三方element-ui组件
import ElementUI from 'element-ui'

Vue.use(ElementUI)
// 将axios挂载到原型上面
// 在vue组件中,通过this.$http就可以调用axios实例
Vue.prototype.$http = http

Vue.config.productionTip = false

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

新建mock文件夹

新建index,js文件内容
import Mock from "mockjs";
// 引入home文件随机生成的mock数据
import homeApi from './home'

// 设置200-2000毫米延时请求数据
Mock.setup({
  timeout: '200-2000'
})

// 首页相关
// 拦截的是/home/getData , get请求,homeApi.getHomeData返回结果作为一个响应式,返回到拦截的ajax
Mock.mock(/\/home\/getOnData/, 'get', homeApi.getHomeData)
新建home.js内容
import Mock from 'mockjs'

// 图表数据
let List = []
// 使用mock模拟数据,渲染
export default {
  getHomeData: () => {
    for (let i = 0; i < 7; i++) {
      List.push(
        Mock.mock({
          vue: Mock.Random.float(100, 8000, 0, 2),
          wechat: Mock.Random.float(100, 8000, 0, 2),
          ES6: Mock.Random.float(100, 8000, 0, 2),
          Redis: Mock.Random.float(100, 8000, 0, 2),
          React: Mock.Random.float(100, 8000, 0, 2),
          springboot: Mock.Random.float(100, 8000, 0, 2)
        })
      )
    }
    return {
      code: 20000,// 真实接口,返回200,这里写2万用于区分
      // Random.float(min,max,dmin,dmax) 返回一个随机浮点数
      // min:最小值,max:最大值,dmin:小数部分最小值,dmax:小数部分最大值
      data: {
        // 饼图
        videoData: [
          {
            name: 'springboot',
            value: Mock.Random.float(1000, 10000, 0, 2)
          },
          {
            name: 'vue',
            value: Mock.Random.float(1000, 10000, 0, 2)
          },
          {
            name: '小程序',
            value: Mock.Random.float(1000, 10000, 0, 2)
          },
          {
            name: 'ES6',
            value: Mock.Random.float(1000, 10000, 0, 2)
          },
          {
            name: 'Redis',
            value: Mock.Random.float(1000, 10000, 0, 2)
          },
          {
            name: 'React',
            value: Mock.Random.float(1000, 10000, 0, 2)
          }
        ],
        // 柱状图
        userData: [
          {
            date: '周一',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周二',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周三',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周四',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周五',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周六',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          },
          {
            date: '周日',
            new: Mock.Random.integer(1, 100),
            active: Mock.Random.integer(100, 1000)
          }
        ],
        // 折线图
        orderData: {
          date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
          data: List
        },
        tableData: [
          {
            name: 'ES6',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          },
          {
            name: '小程序',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          },
          {
            name: 'Vue',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          },
          {
            name: 'springboot',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          },
          {
            name: 'React',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          },
          {
            name: 'Redis',
            todayBuy: Mock.Random.float(100, 1000, 0, 2),
            monthBuy: Mock.Random.float(3000, 5000, 0, 2),
            totalBuy: Mock.Random.float(40000, 1000000, 0, 2)
          }
        ]
      }
    }
  }
}

home.less样式

.home{
  // background-color: blueviolet;
  //左侧,个人信息部分
  .user{
    display: flex;
    align-items: center;
    padding-bottom: 20px;
    margin-bottom: 20px;
    border-bottom: 1px solid #ccc;
    img{
      width: 150px;
      height: 150px;
      border-radius: 50%;
      margin-right: 40px;
    }
    .userinfo{
      &:extend(.user); // less中 的继承写法
      .name{
        max-width: 120px;
        font-size: 32px;
        margin-bottom: 20px;
        overflow: hidden;
          /*超出隐藏*/
          text-overflow: ellipsis;
          /*隐藏后添加省略号*/
          white-space: nowrap;
          /*强制不换行*/
      }
      .name:hover{
        overflow: visible;
      }
      .access{
        color: #999999;
      }
    }
  }
  // 登录时间,登录地址样式
  .login-info{
    p{
      line-height: 28px;
      font-size: 14px;
      color: #999999;
      span{
        color: #666666;
        margin-left: 60px;
      }
    }
  }
  // 右侧顶部,卡片部分
  .num{
    display: flex;
    flex-wrap: wrap; //超出换行
    justify-content: space-between; // 两端对齐
    .el-card{
      width: 32%;
      margin-bottom: 20px;
      /deep/ .el-card__body{
        display: flex;
        padding: 0;
      }
    }
    .icon{
      font-size: 30px;
      width: 80px;
      height: 80px;
      text-align: center;
      line-height: 80px;
      color: #fff;
    }
    .detail{
      margin-left:15px;
      display: flex;
      flex-direction: column; //垂直分布
      justify-content: center; // 垂直居中
      .num{
        font-size: 30px;
        margin-bottom: 10px;
      }
      .txt{
        font-size: 14px;
        text-align: center;
        color: #999999;
      }
    }
  }
  // 右侧,底部each图表部分
  .graph{
    margin-top: 20px;
    display: flex;
    justify-content: space-between;
    .el-card{
      width: 48%;
    }
  }
}
封装axios请求文件(新建api文件夹,里面存放config.js)
import axios from "axios";

// 创建一个axios实例
const service = axios.create({
  // 请求超时时间
  timeout: 3000
})

// 添加请求拦截器(interceptors就是请求拦截器)
service.interceptors.request.use(
  // 请求成功返回的参数
  config => {
    return config
  },
  err => {
    console.log(err);
  }
)

// 响应拦截器
service.interceptors.response.use(
  response => {
    let res = {}
    // 判断状态码
    res.status = response.status
    res.data = response.data
    return res
  }, //失败返回参数
  err => console.log(err)
)
// 千万不要忘记将,方法抛出去
export default service
标签: echarts ui vue.js

本文转载自: https://blog.csdn.net/weixin_46426412/article/details/129113119
版权归原作者 姜香小白鱼 所有, 如有侵权,请联系我们删除。

“VUE2+Element-ui+封装Echarts图表”的评论:

还没有评论