vue3+ts中封装echarts

本文介绍如何在Vue3项目中结合TypeScript封装ECharts组件,从新建components/chart/index.vue开始,详细阐述代码实现过程,并展示了组件在页面上的实际效果,包括切换按钮的交互功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 新建components文件下chart文件的index.vue,废话不多说,上代码

<template>
  <v-chart
    ref="myChart"
    class="echarts"
    :style="{ height: height }"
    :option="option"
    autoresize
  />
</template>

<script lang="ts" setup>
  import VChart from 'vue-echarts';
  import { computed } from 'vue';
  import _ from 'lodash';

  const props = defineProps({
    dataSource: {
      type: Object,
      default: () => {
        return {};
      },
    },
    chartOption: {
      type: Object,
      default: () => {
        return {};
      },
    },
    height: {
      type: String,
      default: '300px',
    },
    unit: {
      type: String,
      default: '',
    },
  });

  const option = computed(() => {
    return {
      // title: _.assign({}, defaultOption.title, props.chartOption.title || {}),
      tooltip: _.assign(
        {},
        defaultOption.tooltip,
        props.chartOption.tooltip || {}
      ),
      grid: _.assign({}, defaultOption.grid, props.chartOption.grid || {}),
      legend: _.assign(
        {},
        defaultOption.legend,
        props.chartOption.legend || {}
      ),
      xAxis: _.assign({}, defaultOption.xAxis, props.chartOption.xAxis, {
        data: props.dataSource.xAxis,
      }),
      yAxis: _.assign({}, defaultOption.yAxis, props.chartOption.yAxis || {}),
      series: _.map(
        props.dataSource.yAxis,
        (dataItem: {
          symbol: unknown;
          smooth: boolean;
          symbolSize: unknown;
          showSymbol: unknown;
          data: string | unknown[];
          name: unknown;
          color: unknown;
        }) => {
          return {
            type: props.unit || 'line',
            symbol: dataItem.symbol || 'emptyCircle',
            smooth: dataItem.smooth || true,
            symbolSize: dataItem.symbolSize || 8,
            showSymbol: dataItem.showSymbol || true,
            name: dataItem.name,
            data: dataItem.data,
            itemStyle: {
              color: dataItem.color || '#5856D6',
              borderColor: 'rgba(255,255,255,0.8)',
              borderWidth: 2,
            },
            // universalTransition: true,
            // animationDurationUpdate: 1500,
          };
        }
      ),
    };
  });

  const defaultOption = {
    title: {
      x: '5%',
    },
    tooltip: {
      trigger: 'axis',
      textStyle: {
        color: '#fff',
      },
      backgroundColor: 'rgba(51,51,51,0.80)',
      padding: [14, 20],
    },
    grid: {
      top: '10',
      left: '0',
      right: '10',
      bottom: '0',
      containLabel: true,
    },
    legend: {
      orient: 'vertical',
      left: 'center',
      bottom: '26',
      itemGap: 25,
      itemWidth: 8,
      itemHeight: 8,
      show: false,
      icon: 'circle',
      textStyle: {
        color: () => {
          return _.map(props.dataSource.yAxis, (item: { color: any }) => {
            return item.color;
          });
        },
      },
    },
    xAxis: {
      axisLabel: {
        margin: 12,
        color: '#666',
      },
      axisTick: {
        show: false,
      },
      axisLine: {
        lineStyle: {
          color: '#E8E8E8',
        },
      },
      splitLine: {
        show: false,
      },
    },
    yAxis: {
      minInterval: 0.2,
      splitNumber: 5,
      axisLine: {
        show: true,
        lineStyle: {
          color: '#E8E8E8',
        },
      },
      splitLine: {
        show: true,
        lineStyle: {
          color: '#E8E8E8',
          opacity: 0.8,
          type: 'dotted',
        },
      },
      axisTick: {
        show: false,
      },
      axisLabel: {
        color: '#666',
      },
    },
  };
</script>

<!--<script lang="ts">-->
<!--  export default {-->
<!--    name: 'ECharts',-->
<!--  };-->
<!--</script>-->

<style lang="less" scoped>
  .echarts {
    width: 100%;
    //height: 100%;
    height: 300px;
  }
</style>

2 使用组件

<template>
  <div class="data-chart">
    <a-card title="数据图表" :bordered="false">
      <template #extra>
        <a-radio-group v-model="radio" type="button" @change="changeRadio">
          <a-radio :value="1">语数外</a-radio>
          <a-radio :value="2">政史地</a-radio>
        </a-radio-group>
      </template>
      <Charts height="300px" :dataSource="dataSource"></Charts>
    </a-card>
  </div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'

const radio = ref<number>(1) // 按钮
const xAxis = ref<string[]>([])
const chartsData = ref<any[]>([])
const dataSource = ref({
  xAxis: xAxis,
  yAxis: chartsData
})

// 模拟页面渲染就加载图表数据
const fetchData = () => {
  xAxis.value = ['星期一', '星期二', '星期三', '星期四', '星期五']
  chartsData.value = [
    {
      name: '语文',
      color: '#FF6F00',
      data: [0, 0, 0, 0, 0]
    },
    {
      name: '数学',
      color: '#FFB903',
      data: [34, 86, 67, 34, 89]
    },
    {
      name: '英语',
      color: '#3D8BFF',
      data: [66, 83, 45, 77, 73]
    }
  ]
}

// 点击按钮切换图标数据(根据自己的接口业务需求调整)
const changeRadio = () => {
  if (radio.value === 1) {
    chartsData.value = [
      {
        name: '语文',
        color: '#FF6F00',
        data: [0, 0, 0, 0, 0]
      },
      {
        name: '数学',
        color: '#FFB903',
        data: [34, 86, 67, 34, 89]
      },
      {
        name: '英语',
        color: '#3D8BFF',
        data: [66, 83, 45, 77, 73]
      }
    ]
  } else {
    chartsData.value = [
      {
        name: '政治',
        color: '#FF6F00',
        data: [45, 56, 24, 87, 45]
      },
      {
        name: '历史',
        color: '#FFB903',
        data: [34, 86, 67, 34, 89]
      },
      {
        name: '地理',
        color: '#3D8BFF',
        data: [66, 83, 45, 77, 73]
      }
    ]
  }
}
</script>

3 页面效果,切换按钮也是没问题
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值