闲时基于上次封装的图表组件做了一层优化,话不多说,间接上代码吧

Step-1: 新建一个config.ts文件

export const config = {  labelKey: "name",  valueKey: "value",};export type chartDataItemType = {  [key: string]: string | number;};// 以后反对显示的图表类型(折线,柱形)export type chartSupportType = "line" | "bar";export type chartDataType = {  name: string;  data: chartDataItemType[];  type: chartSupportType;  labelKey?: string;  valueKey?: string;  options?: any;};export type chartOptionsType = {  [key: string]: any;};// 根底图例色彩数据export const baseColorArr = [  "#3CD7D7",  "#F9CB28",  "#A089FF",  "#5CC4FF",  "#FF9292",  "#5CC4FF",  "#FF8AEC",  "#FFB35B",];// 暗影区域色彩数据export const areaColorArr = [  "#C5F3F3",  "#FDEFBF",  "#dcd3ff",  "#bde7ff",  "#ffd3d3",  "#bde7ff",  "#ffd0f7",  "#ffe0bd",];// 图例顶部字体大小export const defaultLabelFontsize = 8;export const getColor = (index, type: "default" | "area" = "default") => {  const colorArr = type === "default" ? baseColorArr : areaColorArr;  const colorIndex = index % colorArr.length;  return colorArr[colorIndex];};// 图表底部滚动条默认款式export const defaultDataZoomOptions: any[] = [  {    type: "slider",    show: true,    xAxisIndex: [0],    start: 0,    end: 30,    textStyle: {      color: "#ccd7d7",    },  },];// 获取滚动条款式export const getDataZoom = (seriesLength, showZoomLength) => {  if (seriesLength > showZoomLength) {    return defaultDataZoomOptions;  } else {    return [];  }};// 获取折线图、柱形图根底配置export const getLineBarBaseOptions = (seriesLength, showZoomLength = 7) => {  return {    tooltip: {      trigger: "axis",      axisPointer: {        type: "shadow",      },    },    grid: {      left: "3%",      right: "4%",      bottom: "3%",      containLabel: true,    },    yAxis: {      type: "value",    },    dataZoom: getDataZoom(seriesLength, showZoomLength),  };};// 获取折线系列配置export const getLineSeriesOptions = (index) => {  return {    tooltip: {      trigger: "axis",    },    areaStyle: {      color: getColor(index, "area"),    },    smooth: true,    label: {      show: true, //开启显示      position: "top", //在上方显示      //数值款式      color: getColor(index, "default"),      fontSize: defaultLabelFontsize,    },  };};// 获取柱形系列配置export const getBarSeriesOptions = (index) => {  return {    barWidth: 10,    label: {      show: true, //开启显示      position: "top", //在上方显示      //数值款式      color: getColor(index, "default"),      fontSize: defaultLabelFontsize,    },    itemStyle: {      borderRadius: [6, 6, 0, 0],    },  };};

Step-2: 新建一个index.vue文件

<!--/*** Author: 前端小高* Date: 2023-05-08 14:58* Desc: MyChart 文件形容*/--><template>  <div ref="chartDom" class="chart-dom"></div></template><script name="MyChart" lang="ts" setup>import { ref, computed, watch, onMounted, onBeforeUnmount, PropType, nextTick } from "vue";import * as ECharts from "echarts";import { debounce } from "lodash";import {  baseColorArr,  chartDataType,  chartOptionsType,  chartSupportType,  chartDataItemType,  getLineBarBaseOptions,  getLineSeriesOptions,  getBarSeriesOptions,  config,} from "./config";const props = defineProps({  color: {    type: Array as PropType<string[]>,    default: () => {      return baseColorArr;    },  },  // 超过该数字时显示滚动条  showZoomLimit: {    type: Number,    default: 7,  },  // 坐标轴是否两边留白  isBoundaryGap: {    type: Boolean,    default: false,  },  baseOptions: {    type: Object as PropType<chartOptionsType>,    default: () => {      return {};    },  },  data: {    type: Array as PropType<chartDataType[]>,    require: true,  },});const emits = defineEmits(["chart-click"]);const initSeriesData = () => {  if (props?.data?.length) {    getXAxisDataArr();    const tempSeriesArr = props?.data.map((item: chartDataType, index: number) => {      const chartOptions = getSeriesItemOptions(item, index);      return {        name: item.name,        data: getValueArr(item.data, item?.valueKey),        type: item.type,        ...chartOptions,      };    });    const tempLegendDataArr = props?.data.map((item: chartDataType) => item.name);    legendDataArr.value = tempLegendDataArr;    seriesArr.value = tempSeriesArr;  }};const getXAxisDataArr = () => {  const labelName = props?.data?.[0]?.labelKey || config.labelKey;  const xDataArr = props?.data?.[0]?.data.map((item) => item[labelName]);  dataArr.value = xDataArr as string[];};const callbackMap = {  line: getLineSeriesOptions,  bar: getBarSeriesOptions,};const getSeriesItemDefaultOptions = (type: chartSupportType = "line") => {  return callbackMap[type];};const getChartBaseOptions = () => {  return getLineBarBaseOptions;};const getSeriesItemOptions = (chartItem: chartDataType, index = 0) => {  const cb = getSeriesItemDefaultOptions(chartItem.type);  const defaultOptions = cb(index);  if (chartItem?.options) {    const mergeOptions = Object.assign({}, defaultOptions, chartItem?.options);    return mergeOptions;  } else {    return defaultOptions;  }};const getBaseChartOptions = () => {  const cb = getChartBaseOptions();  const baseOptions = cb(dataArr.value.length, props.showZoomLimit);  if (props?.baseOptions) {    const mergeOptions = Object.assign({}, baseOptions, props?.baseOptions);    return mergeOptions;  } else {    return baseOptions;  }};const getValueArr = (arr: chartDataItemType[], valueKey?: string) => {  const keyName = valueKey ? valueKey : config.valueKey;  return arr.map((item) => Number(item[keyName]));};const resizeHandler = () => {  chartExample.resize();};const resizeHandlerOrigin = debounce(resizeHandler, 300);const dataArr = ref<any[]>([]);const seriesArr = ref<any[]>([]);const legendDataArr = ref<string[]>([]);const getOptions = computed(() => {  const baseOptions = getBaseChartOptions();  const options = {    color: props.color,    ...baseOptions,    legend: {      data: legendDataArr.value,    },    xAxis: {      type: "category",      data: dataArr.value,      boundaryGap: props.isBoundaryGap,      axisTick: {        alignWithLabel: true,      },    },    series: seriesArr.value,  };  return options;});watch(  () => props.data,  () => {    init();  },  {    deep: true,  });const chartDom = ref();let chartExample: any = null;const initChart = () => {  if (chartExample) {    // 若存在图表实例,则先执行销毁操作    chartExample.dispose();  }  nextTick(() => {    chartExample = ECharts.init(chartDom.value);    const options = getOptions.value;    chartExample.setOption(options, true);    initResizerListener();    initChartEvent();  });};const initResizerListener = () => {  window.removeEventListener("resize", resizeHandlerOrigin);  window.addEventListener("resize", resizeHandlerOrigin);};const initChartEvent = () => {  cancelClickEvent();  chartExample.on("click", (params) => {    emits("chart-click", params);  });};const cancelClickEvent = () => {  chartExample.off("click");};const init = () => {  initSeriesData();  initChart();};onMounted(() => {  init();});onBeforeUnmount(() => {  cancelClickEvent();  window.removeEventListener("resize", resizeHandlerOrigin);  chartExample.dispose();});</script><style lang="scss" scoped>.chart-dom {  height: 300px;}</style>

Step-3:页面下的援用形式

<!--/*** Author: 前端小高* Date: 2023-05-08 14:55* Desc: ChartComp 图表组件*/--><template>  <my-chart :data="dataArr"></my-chart></template><script name="ChartComp" lang="ts" setup>import { ref } from "vue";import { chartDataType } from "@/common/MyChart/config";const dataArr = ref<chartDataType[]>([  {    name: "测试数据列1",    type: "line",    data: [      {        name: "1.1",        value: 1,      },      {        name: "1.2",        value: 2,      },      {        name: "1.3",        value: 3,      },      {        name: "1.1",        value: 1,      },    ],  },]);</script>

页面展现成果如下

代码Gitee地址

比照根底版本的echarts封装组件,2.0版本做了如下优化

  • 只需传入渲染数据及展现数据类型,即可渲染
  • 其余图表配置能够按需传入
  • (不足之处:以后只做了折线图及柱形图的反对,其余类型图表各位能够按需扩大)

Remark: 如果有帮忙到各位或者给各位封装组件提供了一点思路,无妨点个赞吧。。。