E charts 封装使用

194 阅读2分钟

前言

项目中经常使用echarts,也没有很优雅的使用,一直想做一个自己的代码库,将平时工作中的demo存放

github: gitee.com/shen_xu_he/…

项目说明

技术栈: vue2 + router + vuex + echarts(5.x) + elementUI
封装目的: 封装 echart 基本设施,能在项目中达到开箱即用的效果 封装思想:

  • 抽离引入的echarts,注册及逻辑(按需导入)
  • 封装echarts 组件
  • 实现 屏幕自适应、组件销毁时释放实例、数据响应式等
  • 这种方式可能满足不了所有场景,但是足以应对大多是简单场景,在封装基本功能时,考虑到一些特殊场景,没有再进行深度封装了,大家如果有好的、普遍的场景,欢迎大家进行补充

封装步骤

1. 环境搭建

// vue2 环境下
yarn add element-ui
yarn add echarts

2. 全局配置element

//  全局注册 elementUI
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.use(ElementUI);

3. 封装 @/utils/echarts.js

使用的是按需加载,如果有新的图表,需要在这个文件添加配置

/**
 * 作用:按需引入 echarts 减少打包体积,在 NormalEchats 组件中使用
 * 说明:根据 官网实例,对比出没有的配置项 进行加入
 *
 */
// 1.引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from "echarts/core";
// 2.引入柱状图图表,图表后缀都为 Chart
import { BarChart } from "echarts/charts";
// 3.引入提示框,标题,直角坐标系组件,组件后缀都为 Component
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
} from "echarts/components";

// 4.引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from "echarts/renderers";

// 注册必须的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  BarChart,
  CanvasRenderer,
]);

export default echarts;

封装 BaseEchart.vue 组件

这里的宽高没有用 style 动态传入,我想的是要兼容 rem等 单位的布局,因此视图的宽高由父盒子的大小进行设置

<template>
  <div :ref="refName" class="chartBox" />
</template>

<script>
// 引入 配置完成的 echarts
import echarts from "@/utils/echarts";
// 引入默认配置项,

export default {
  name: "BaseEchars",
  props: {
    refName: {
      // 图例绑定的dom  一个页面中存在多个图例时不要重复
      type: String,
      required: true,
    },
    option: {
      // echarts 配置项  直接从官网复制粘贴即可
      required: true,
    },
  },
  data() {
    return {
      chart: null, // echarts 实例
    };
  },
  watch: {
    // 监听 echarts 变化 自动更新
    option: {
      deep: true,
      handler() {
        console.log("数据变化了,视图更新了");
        this.chart.setOption(this.chartOption);
        this.$emit("getChart", this.chart);
      },
    },
  },
  computed: {
    defaultOption() {
      //默认配置项   这里的默认配置项 只能兼容 option 第一层级的属性
      return {
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "cross",
            label: {
              backgroundColor: "#6a7985",
            },
          },
        },
      };
    },
    chartOption() {
      // 最终配置项
      return { ...this.defaultOption, ...this.option };
    },
  },
  methods: {
    // 初始化实例
    initChart() {
      this.chart = echarts.init(this.$refs[this.refName]);
      // 当前配置项 优先级大于 默认配置项
      // console.log("当前视图的配置项", this.chartOption);
      this.chart.setOption(this.chartOption);
      this.$emit("getChart", this.chart);
    },
    // 自适应
    resizeHandler() {
      this.chart.resize();
    },
  },
  mounted() {
    // 如果传入的 option 为空则不进行初始化
    if (!this.option || this.option === "{}") {
      return;
    }
    this.initChart();
    window.addEventListener("resize", this.resizeHandler);
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    window.removeEventListener("resize", this.resizeHandler);
    this.chart.dispose();
    this.chart = null;
  },
};
</script>

<style scoped>
.chartBox {
  width: 100%;
  height: 100%;
}
</style>

使用 BaseEchart 组件

<template>
  <div class="com_box">
    <div @click="changeData">改变数据</div>
    <BaseEchart refName="baseBar" :option="option" @getChart="getChart" />
  </div>
</template>

<script>
export default {
  name: "BaseBar",
  data() {
    return {
      xAxisData: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
      seriesData: [120, 200, 150, 80, 70, 110, 130],
      chart: null,
    };
  },
  computed: {
    option() {
      // return null;
      let barData = {
        xAxis: {
          type: "category",
          data: this.xAxisData,
        },
        yAxis: {
          type: "value",
        },
        series: [
          {
            data: this.seriesData,
            type: "bar",
          },
        ],
      };
      return barData;
    },
  },
  methods: {
    // 模拟动态数据
    changeData() {
      this.xAxisData.push("test");
      this.seriesData.push(100);
    },
    // 获取子组件 echarts 的实例
    getChart(chart) {
      console.log("获取子组件 echarts 的实例", chart);
    },
  },
};
</script>

<style scoped>
.com_box {
  width: 100%;
  height: 400px;
  /* background-color: red; */
}
</style>