vue2.x-echarts公共组件封装

126 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情 >>

一、mixins

混入(mixins)是一种分发Vue组件中可复用功能的非常灵活的方式。

组件在引用之后相当于在父组件内开辟了一块单独的空间,来根据父组件props过来的值进行相应的操作,单本质上两者还是泾渭分明,相对独立。

而mixins则是在引入组件之后,则是将组件内部的内容如data等方法、method等属性与父组件相应内容进行合并。相当于在引入后,父组件的各种属性方法都被扩充了。

单纯组件引用: 父组件 + 子组件 >>> 父组件 + 子组件
mixins: 父组件 + 子组件 >>> new父组件

有点像注册了一个vue的公共方法,可以绑定在多个组件或者多个Vue对象实例中使用。另一点,类似于在原型对象中注册方法,实例对象即组件或者Vue实例对象中,仍然可以定义相同函数名的方法进行覆盖,有点像子类和父类的感觉。

mixins封装的自适应工具resize的作用是:给echarts添加自适应窗口大小功能

二、代码示例

父组件:

// 父组件调用代码
<template>
  <div class="exemplify3">
    <div class="chart_box">
      <DoubleLineChart :chart-data="DoubleLineChartData"></DoubleLineChart>
    </div>
  </div>
</template>
<script>
import DoubleLineChart from "../components/Charts/DoubleLineChart/index.vue";
export default {
  components: {
    DoubleLineChart,
  },
  data() {
    return {
      DoubleLineChartData: {
        xData: ["2018", "2019", "2020", "2021", "2022"],
        color: ["#038BFF", "#32DBEF"],
        data: [
          {
            // title: "告警",
            data: [500, 1100, 600, 900, 700],
          },
          {
            // title: "故障",
            data: [600, 900, 700, 1100, 550],
          },
        ],
      },
    };
  },
};
</script>

封装的echarts折线图公共组件:

// 封装的echarts折线图公共组件
<template>
  <div
    :class="className"
    :style="{ height:height,width:width }"
  />
</template>

<script>
import * as echarts from "echarts";
import resize from "../mixin/resize";  // 用于echarts自适应窗口

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "240px",
    },
    autoResize: {
      type: Boolean,
      default: true,
    },
    chartData: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      chart: null,
    };
  },
  watch: {
    chartData: {
      deep: true,
      handler(val) {
        this.setOptions(val);
      },
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$el, "macarons");
      this.setOptions(this.chartData);
    },
    setOptions({ xData, yName, color, data } = {}) {
      const { seriesList } = this.createSeries(data);
      this.chart.setOption({
        backgroundColor: "transparent",
        grid: {
          left: "5%",
          right: "10%",
          top: "20%",
          bottom: "10%",
          containLabel: true,
        },
        tooltip: {
          trigger: "axis",
        },
        color,
        xAxis: {
          type: "category",
          boundaryGap: false,
          data: xData,
          axisTick: {
            show: false,
          },
          axisLabel: {
            textStyle: {
              color: "rgba(154, 161, 179, 1)",
            },
          },
        },
        yAxis: {
          name: yName,
          type: "value",
          splitLine: {
            show: true,
            lineStyle: {
              width: 0.5,
              color: "#A1A7B3",
              type: "dashed",
            },
          },
          axisLine: {
            show: true,
          },
        },
        series: seriesList,
      });
    },
    createSeries(data) {
      const legend = [];
      const companySeries = function (name, color, data) {
        return {
          name: name,
          type: "line",
          showSymbol: false,
          itemStyle: {
            normal: {
              color: color,
              lineStyle: {
                color: color,
                width: 1,
              },
            },
          },
          areaStyle: {
            normal: {
              color: new echarts.graphic.LinearGradient(
                0,
                0,
                0,
                1,
                [
                  {
                    offset: 0,
                    color: "rgba(3, 139, 255, 0.4)",
                  },
                  {
                    offset: 1,
                    color: "rgba(3, 139, 255, 0)",
                  },
                ],
                false
              ),
            },
          },
          data: data,
        };
      };
      const seriesList = data.map((item) => {
        legend.push(item.title);
        return companySeries(item.title, item.color, item.data);
      });
      return { seriesList, legend };
    },
  },
};
</script>

三、最终效果

可复用的折线图截图如下:

微信截图_20220810160140.png