vue2中使用Echarts(封装)

2,105 阅读4分钟

Echarts在Vue2中的封装(可以直接cv套用~)

在这里做一个适用于饼图、折线图、柱状图的简单封装,其他配置项按项目需求自行添加或改造即可。

(效果图在最后)

1.封装echarts组件

1.引入echarts(跳转自行查看)这里省去安装与main.js引入部分

<template>
  <!-- 绑定容器 -->
  <div ref="echart"></div>
</template>
<script>
  import * as echart from "echarts";
</script>

2.配置echarts接收的数据,因为常用的图表有饼图折线图柱状图等,所以这里只做有轴无轴表的区分

export default {
  props: {
    //是否为有轴图表
    isAxisChart: {
      type: Boolean,
      default: true,
    },
    //图表数据
    chartData: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  //监听图表数据变化
  watch: {
    chartData: {
      handler: function () {
        this.initChart();
      },
      deep: true,
    },
  },
}

3.对图表的选项进行配置,这里仅配置了一些常用选项(字体颜色、提示框、XY轴、图表类型等)

data() {
    return {
      //有轴表配置项
      axisOptions: {
        legend: {
          //字体颜色
          textStyle: {
            color: "#333",
          },
        },
        //grid组件离容器左侧的距离
        grid: {
          left: "20%",
        },
        //提示框触发规则
        tooltip: {
          trigger: "item",
        },
        //X轴配置
        xAxis: {
          type: "category",
          data: [],
          axisLine: {
            lineStyle: {
              color: "#17b3a3",
            },
          },
          axisLabel: {
            interval: 0, //X轴间隔
            color: "#17b3a3",
          },
        },
        //Y轴配置
        yAxis: [
          {
            type: "value",
            axisLine: {
              lineStyle: {
                color: "#17b3a3",
              },
            },
          },
        ],
        //颜色配置
        color: [
          "#2ec7c9",
          "#b6a2de",
          "#5ab1ef",
          "#ffb980",
          "#d87a80",
          "#8d98b3",
        ],
        //图表类型与数据
        series: [],
      },
      //无轴表配置项
      normalOptions: {
        //提示框触发规则
        tooltip: {
          trigger: "item",
        },
        //颜色配置
        color: [
          "#0f78f4",
          "#dd536b",
          "#9462e5",
          "#a6a6a6",
          "#e1bb22",
          "#39c362",
          "#3ed1cf",
        ],
        //图表类型与数据
        series: [],
      },
    };
  },

4.根据父组件需要的图表类型对props中的数据进行分发

methods: {
    //根据图表类型配置图表项
    initChart() {
      this.initChartData();
      if (this.echart) {
        this.echart.setOption(this.options);
      } else {
        this.echart = echart.init(this.$refs.echart);
        this.echart.setOption(this.options);
      }
    },
    //根据图表类型导入图表数据
    initChartData() {
      if (this.isAxisChart) {
        //设置X轴
        this.axisOptions.xAxis.data = this.chartData.xData;
        //设置图表类型
        this.axisOptions.series = this.chartData.series;
      } else {
        //无轴表
        this.normalOptions.series = this.chartData.series;
      }
    },
  },
  computed: {
    options() {
      return this.isAxisChart ? this.axisOptions : this.normalOptions;
    },
  },

5.对上面三步骤进行的整合,该部分可直接CV拿去创建自己的图表封装组件

<template>
  <!-- 绑定容器 -->
  <div ref="echart"></div>
</template>

<script>
import * as echart from "echarts";
export default {
  props: {
    //是否为有轴图表
    isAxisChart: {
      type: Boolean,
      default: true,
    },
    //图表数据
    chartData: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  //监听图表数据变化
  watch: {
    chartData: {
      handler: function () {
        this.initChart();
      },
      deep: true,
    },
  },
  methods: {
    //根据图表类型配置图表项
    initChart() {
      this.initChartData();
      if (this.echart) {
        this.echart.setOption(this.options);
      } else {
        this.echart = echart.init(this.$refs.echart);
        this.echart.setOption(this.options);
      }
    },
    //根据图表类型导入图表数据
    initChartData() {
      if (this.isAxisChart) {
        //设置X轴
        this.axisOptions.xAxis.data = this.chartData.xData;
        //设置图表类型
        this.axisOptions.series = this.chartData.series;
      } else {
        //无轴表
        this.normalOptions.series = this.chartData.series;
      }
    },
  },
  computed: {
    //判断图表类型
    options() {
      return this.isAxisChart ? this.axisOptions : this.normalOptions;
    },
  },
  data() {
    return {
      //有轴表配置项
      axisOptions: {
        legend: {
          //字体颜色
          textStyle: {
            color: "#333",
          },
        },
        //grid组件离容器左侧的距离
        grid: {
          left: "20%",
        },
        //提示框触发规则
        tooltip: {
          trigger: "item",
        },
        //X轴配置
        xAxis: {
          type: "category",
          data: [],
          axisLine: {
            lineStyle: {
              color: "#17b3a3",
            },
          },
          axisLabel: {
            interval: 0, //X轴间隔
            color: "#17b3a3",
          },
        },
        //Y轴配置
        yAxis: [
          {
            type: "value",
            axisLine: {
              lineStyle: {
                color: "#17b3a3",
              },
            },
          },
        ],
        //颜色配置
        color: [
          "#2ec7c9",
          "#b6a2de",
          "#5ab1ef",
          "#ffb980",
          "#d87a80",
          "#8d98b3",
        ],
        //图表类型
        series: [],
      },
      //无轴表配置项
      normalOptions: {
        //提示框触发规则
        tooltip: {
          trigger: "item",
        },
        //颜色配置
        color: [
          "#0f78f4",
          "#dd536b",
          "#9462e5",
          "#a6a6a6",
          "#e1bb22",
          "#39c362",
          "#3ed1cf",
        ],
        //图表类型
        series: [],
      },
    };
  },
};
</script>

2.在页面中使用组件

在这里整合了三种图(饼图、折线图、柱状图),需要固定父组件图表数据的数据对象属性以适配该组件(见注释图表数据),且重点在图表数据配置项seriesxData数据处理部分,每种图表对其数据的处理方式各有不同,具体看mounted里的处理方式(现实开发中以后端返回的数据结构为准)

<template>
  <el-row>
    <el-col :span="12">
      <el-card shadow="hover" class="middle">
        <!-- 饼图 -->
        <EchartsView
          :chartData="pieData"
          style="height: 700px"
          :isAxisChart="false"
        />
      </el-card>
    </el-col>
    <el-col :span="11" style="margin-left: 20px; margin-top: 20px">
      <el-card shadow="hover">
        <!-- 折线图 -->
        <EchartsView :chartData="lineData" style="height: 375px" />
      </el-card>
      <el-card shadow="hover">
        <!-- 柱状图 -->
        <EchartsView :chartData="barData" style="height: 375px" />
      </el-card>
    </el-col>
  </el-row>
</template>

<script>
import EchartsView from "@/components/MAG_echarts.vue";
import MockData from "./mock.json";
export default {
  components: {
    EchartsView,
  },
  data() {
    return {
      //图表数据(接取数据适配组件)
      lineData: { xData: [], series: [] },
      barData: { xData: [], series: [] },
      pieData: { series: [] },
    };
  },
  mounted() {
    //模拟从后端接取数据
    let data = MockData;
    //饼图
    this.pieData.series = [
      {
        //获取的数据
        data: data.pieData,
        //饼图类型
        type: "pie",
      },
    ];
    //折线
    const keyArray = Object.keys(data.lineData.data[0]); //遍历取出数据名称
    const series = [];
    keyArray.forEach((key) => {
      series.push({
        name: key, //数据名称
        data: data.lineData.data.map((item) => item[key]), //取值
        type: "line", //折线类型
      });
    });
    this.lineData.xData = data.lineData.date; //X轴数据
    this.lineData.series = series;
    //柱状图
    this.barData.xData = data.barData.map((item) => item.date); //X轴数据
    this.barData.series = [
      {
        name: "新增用户", //柱列名
        data: data.barData.map((item) => item.new), //对应数据
        type: "bar", //柱状类型
      },
      {
        name: "活跃用户", //柱列名
        data: data.barData.map((item) => item.active), //对应数据
        type: "bar",
      },
    ];
  },
};
</script>


最后附上模拟数据(json格式文件)以方便实践

{
  "pieData": [
    {
      "name": "小米",
      "value": 2999
    },
    {
      "name": "苹果",
      "value": 5999
    },
    {
      "name": "vivo",
      "value": 1500
    },
    {
      "name": "魅族",
      "value": 2599
    },
    {
      "name": "oppo",
      "value": 2200
    },
    {
      "name": "三星",
      "value": 4399
    }
  ],
  "barData": [
    {
      "date": "周一",
      "new": 5,
      "active": 200
    },
    {
      "date": "周二",
      "new": 10,
      "active": 500
    },
    {
      "date": "周三",
      "new": 12,
      "active": 550
    },
    {
      "date": "周四",
      "new": 60,
      "active": 800
    },
    {
      "date": "周五",
      "new": 70,
      "active": 850
    },
    {
      "date": "周六",
      "new": 73,
      "active": 900
    },
    {
      "date": "周天",
      "new": 5,
      "active": 200
    }
  ],
  "lineData": {
    "date": ["1", "2", "3", "4", "5", "6", "7"],
    "data": [
      {
        "苹果": 5449,
        "vivo": 386,
        "oppo": 7259,
        "魅族": 2162,
        "三星": 787,
        "小米": 2989
      },
      {
        "苹果": 1631,
        "vivo": 4883,
        "oppo": 1938,
        "魅族": 1580,
        "三星": 3186,
        "小米": 2900
      },
      {
        "苹果": 6449,
        "vivo": 3665,
        "oppo": 1336,
        "魅族": 6206,
        "三星": 6746,
        "小米": 1714
      },
      {
        "苹果": 1753,
        "vivo": 3342,
        "oppo": 560,
        "魅族": 1976,
        "三星": 2260,
        "小米": 4177
      },
      {
        "苹果": 3024,
        "vivo": 3362,
        "oppo": 1425,
        "魅族": 731,
        "三星": 7170,
        "小米": 2777
      },
      {
        "苹果": 2686,
        "vivo": 7326,
        "oppo": 1936,
        "魅族": 6962,
        "三星": 1338,
        "小米": 7573
      },
      {
        "苹果": 2445,
        "vivo": 3797,
        "oppo": 2455,
        "魅族": 1409,
        "三星": 5121,
        "小米": 3048
      }
    ]
  }
}

3.效果图

图例.png