Vue3自定义Echars组件附带全局配置方式

 更新时间:2024年03月11日 09:15:58   作者:Circle_Key  
这篇文章主要介绍了Vue3自定义Echars组件附带全局配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Vue3自定义Echars组件附带全局配置

<template>
  <div ref="chart"  :id="id"  :class="className" :style="{ height: height, width: width }"></div>
</template>
 
<script setup>
import { ref, reactive, toRefs, onMounted, onBeforeUnmount,watch } from 'vue'
import * as echarts from 'echarts';
 
// 传递参数
const props = defineProps({
  className: {
      type: String,
      default: 'chart'
    },
    id: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '280px'
    },
    options: {
      type: Object,
      default: () => { }
    }
})
const chart = ref(null);
 
 
const createChart = () => {
  const myChart = echarts.init(chart.value);
  
   chart.value = echarts.init(chart.value, 'tdTheme')
  myChart.setOption(props.options,true);
    //  chart.value.setOption(props.options, true)
    window.addEventListener("resize",  () => {
        chart.value.resize()
      })
};
 
watch(() => props.options, (options) => {
  if (chart.value) {
    // 设置true清空echart缓存
    chart.value.setOption(options, true)
  }
}, { deep: true })
onMounted(() => {
  createChart();
});
onBeforeUnmount(() => {
  window.removeEventListener("resize", () => {
        chart.value.resize()
      })
  chart.value.dispose()
  chart.value = null
})
</script>
import Echart from './components/echart/index.vue'
import echarts from 'echarts'
const app = createApp(App)
 
// 将echarts挂载到全局对象上
app.config.globalProperties.$echarts = echarts
 
// 注册全局组件
app.component('Echart', Echart)

案列

<template>
  <div ref="chart" style="width: 600px; height: 400px;"></div>
</template>
 
<script setup>
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
 
const chart = ref(null);
 
const createChart = () => {
  const myChart = echarts.init(chart.value);
  myChart.setOption({
    xAxis: {
      type: 'category',
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    yAxis: {
      type: 'value'
    },
    series: [{
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'bar'
    }]
  });
};
 
onMounted(() => {
  createChart();
});
</script>

vue3封装echarts组件

在开发项目过程中需要封装echarts组件,方便多次使用,以下是封装的详细过程。

前置动作:安装echarts以及resize-observer-polyfill插件

  • 新建echarts.ts文件
import * as echarts from "echarts/core";
/**
 * 这里按需引入使用到的图表类型
 */
import { BarChart, LineChart, type LineSeriesOption, PieChart, type PieSeriesOption } from "echarts/charts";
/**
 * 这里按需引入使用到的配置
 * 特别地 包括MarkPoint markLine等这些也要单独使用 不然在图表中无法显示
 */
import {
  LegendComponent,
  type LegendComponentOption,
  TitleComponent,
  // 组件类型的定义后缀都为 ComponentOption
  type TitleComponentOption,
  TooltipComponent,
  type TooltipComponentOption,
  GridComponent,
  type GridComponentOption,
  DataZoomComponent,
  type DataZoomComponentOption,
  // 数据集组件
  DatasetComponent,
  type DatasetComponentOption,
  // 标记组件
  MarkAreaComponent,
  type MarkAreaComponentOption,
  MarkLineComponent,
  type MarkLineComponentOption,
  MarkPointComponent,
  type MarkPointComponentOption,
  // 内置数据转换器组件 (filter, sort)
  TransformComponent,
} from "echarts/components";

import { LabelLayout, UniversalTransition } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";

import { ref, shallowRef, onMounted, onBeforeUnmount } from "vue";
import ResizeObserver from "resize-observer-polyfill";
import throttle from "lodash/throttle";

/**
 * 引入的配置通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
 */
export type ECOption = echarts.ComposeOption<
  | LineSeriesOption
  | PieSeriesOption
  | LegendComponentOption
  | TitleComponentOption
  | TooltipComponentOption
  | DataZoomComponentOption
  | GridComponentOption
  | DatasetComponentOption
  | MarkAreaComponentOption
  | MarkLineComponentOption
  | MarkPointComponentOption
>;

/**
 * 注册按需引入的组件
 */
echarts.use([
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DataZoomComponent,
  DatasetComponent,
  MarkAreaComponent,
  MarkLineComponent,
  MarkPointComponent,
  TransformComponent,
  BarChart,
  LineChart,
  PieChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer,
]);

export default function useChart() {
  const canvasEl = shallowRef();
  const myChart = shallowRef();
  /**
   * 监听容器宽度变化或者浏览器窗口变化对echarts图表进行自动展示
   * 不用window.addEventListener("resize", resizeFn)的原因是这个方法只是监听浏览器窗口的不变化
   *  -对所在容器的大小变化不进行监听 很难满足开发场景的需求
   */
  const resizeObserver = ref<ResizeObserver>();
  const bindResize = () => {
    const deboundResize = throttle(() => {
      myChart.value?.resize();
    }, 500);

    resizeObserver.value = new ResizeObserver(() => {
      deboundResize();
      // myChart.value?.resize();
    });
    resizeObserver.value.observe(canvasEl.value);
  };
  // 解绑 resize
  const unbindResize = () => {
    resizeObserver.value?.unobserve(canvasEl.value);
  };

  onMounted(() => {
    /**
     * 注册echarts并开启监听容器大小变化
     */
    myChart.value = echarts.init(canvasEl.value);
    bindResize();
  });

  onBeforeUnmount(() => {
    /**
     * 销毁监听和echarts
     */
    unbindResize();
    myChart.value?.dispose();
    myChart.value = null;
  });

  return {
    myChart,
    canvasEl,
  };
}

  • 页面封装
<template>
  <div>
    <div class="chart-container" :style="containerStyle">
      <div v-show="dataEmptyFlag" class="chart-empty">
        <span class="empty-title">暂无数据</span>
      </div>
      <div ref="canvasEl" :style="containerStyle" />
      <div v-show="loading" class="chart-loading"><Spin /></div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { Spin } from "ant-design-vue";
import { ref, watch } from "vue";
import useChart from "./useECharts";
import type { ECOption } from "./useECharts";

interface ChartProps {
  containerStyle?: any;
  loading?: boolean;
  dataEmptyFlag?: boolean;
  options?: ECOption;
}

const props = withDefaults(defineProps<ChartProps>(), {
  containerStyle: {
    height: "990px",
    width: "100%",
  },
  loading: false,
  dataEmptyFlag: false,
});

const { myChart, canvasEl } = useChart();

watch(
  () => props?.options,
  (cur) => {
    if (myChart) {
      /**
       * 这里绘制图表前先清空上一次数据 否则有时候会出现数据残余的情况
       */
      myChart.value.clear();
      myChart.value.setOption(cur);
    }
  },
);
</script>
<style scoped>
.chart-container {
  position: relative;
  width: 100%;
}
.chart-loading {
  align-items: center;
  background-color: #ffffff;
  bottom: 0;
  display: flex;
  justify-content: center;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1999;
}
.chart-empty {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  color: #888;
  font-size: 14px;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
.empty-title {
  font-size: 16px;
  font-weight: 500;
  color: #000;
}
</style>
  • 组件调用
/**
 * 参入对应的参数以及图表配置项
 */
<anewCharts :loading="loading" :data-empty-flag="dataEmptyFlag" :containerStyle="chartStyle" :options="chartOptions"></anewCharts>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

相关文章

  • 微信小程序如何像vue一样在动态绑定类名

    微信小程序如何像vue一样在动态绑定类名

    这篇文章主要介绍了微信小程序如何像vue一样在动态绑定类名,文中给大家提到了vue与微信小程序的区别,需要的朋友可以参考下
    2018-04-04
  • Vue之props 配置详解

    Vue之props 配置详解

    这篇文章主要为大家介绍了Vue之props 配置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助,希望能够给你带来帮助
    2021-11-11
  • vue实现信息管理系统

    vue实现信息管理系统

    这篇文章主要为大家详细介绍了vue实现信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • vue2组件实现懒加载浅析

    vue2组件实现懒加载浅析

    本篇文章主要介绍了vue2组件实现懒加载浅析,运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力.
    2017-03-03
  • Vue3使用postcss-px-to-viewport实现页面自适应

    Vue3使用postcss-px-to-viewport实现页面自适应

    postcss-px-to-viewport 是一个 PostCSS 插件,它可以将 px 单位转换为视口单位,下面我们就看看如何使用postcss-px-to-viewport实现页面自适应吧
    2024-01-01
  • vue项目中的public、static及指定不编译文件问题

    vue项目中的public、static及指定不编译文件问题

    这篇文章主要介绍了vue项目中的public、static及指定不编译文件问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Vue路由跳转问题记录详解

    Vue路由跳转问题记录详解

    本篇文章主要介绍了Vue路由跳转问题记录详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • vue子组件封装弹框只能执行一次的mounted问题及解决

    vue子组件封装弹框只能执行一次的mounted问题及解决

    这篇文章主要介绍了vue子组件封装弹框只能执行一次的mounted问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • vue element-ui读取pdf文件的方法

    vue element-ui读取pdf文件的方法

    这篇文章主要介绍了vue element-ui读取pdf文件的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • vue3中使用scss加上scoped导致样式失效问题

    vue3中使用scss加上scoped导致样式失效问题

    这篇文章主要介绍了vue3中使用scss加上scoped导致样式失效问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10

最新评论