前言

项目环境使用的是 vben admin 框架,业务中想要在当前项目中使用一个 echarts 图表
项目语言使用的是 vue3+TypeScript


一、按需引入 ECharts 图表和组件

当前项目别的位置使用的有 echarts ,已经引入和安装过 echarts 了,所以这就不需要再重新 npm 安装 echarts,只需要按需引用我自己需要的就可以了
官方使用文档 : 按需引入 ECharts 图表和组件
在这里插入图片描述在项目中找到了这个文件 (我自己项目的存放路径是在 src\utils\lib\echarts.ts
在这里插入图片描述
我需要使用的图标是一个仪表盘,官方示例是长这个样子的

在这里插入图片描述
在这里插入图片描述这个图表的类型是 guage
按照官方所说的按需引入,我在原来的文件中的 import 和 use 中分别加上了 GuageChart (我是看别的图表是首字母大写后面加上 Chart 就也这么写了,猜对了~
在这里插入图片描述
在这里插入图片描述

引入到此就 OK 了

二、使用步骤

1.还是先上代码叭

<!--这里是关于满仓率的图表-->
<template>
  <div ref="chartRef" :style="{ width, height }"></div>
</template>
<script lang="ts" setup>
  import { Ref, ref, watch } from 'vue';
  import { useECharts } from '/@/hooks/web/useECharts';

  const props = defineProps({
    loading: Boolean, 
    width: {
      type: String as PropType<string>,
      default: '100%',
    },
    height: {
      type: String as PropType<string>,
      default: '300px',
    },
    ratio: Number,
  });

  const chartRef = ref<HTMLDivElement | null>(null);
  const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  watch(
    () => props.loading,
    () => {
      if (props.loading) {
        return;
      }
      setOptions({
        tooltip: {
          formatter: '{a}<br/>{b} : {c}',
        },
        series: [
          {
            name: '满仓率',
            type: 'gauge',
            progress: {
              show: true,
            },
            detail: {
              valueAnimation: true,
              formatter: function (value) {
                if (!props.ratio) {
                  return '加载中';
                } else {
                  return props.ratio + '%';
                }
              },
              fontSize: 20,
            },
            data: [
              {
                value: props.ratio,
              },
            ],
          },
        ],
      });
    },
    { immediate: true },
  );
</script>

2. 上实现效果 ! ~

在这里插入图片描述

3. 代码分析

我是直接把一个图表封装到这个组件里了,这是个相对很简单的图表,只有关键性参数就是 data 中的那个 value,这个参数是从调用这个组件的位置传过来的

<!--父组件-->
          <Card size="default" :canExpan="false" :bordered="false">
            <Meta description="满仓率" />
            <RemainGuage :ratio="panelObj.fullPercent" /> 
          </Card>

在子组件中接收传过来的参数 ratio

// 子组件
  const props = defineProps({
    loading: Boolean, 
    width: {
      type: String as PropType<string>,
      default: '100%',
    },
    height: {
      type: String as PropType<string>,
      default: '300px',
    },
    ratio: Number, // 传过来的 ratio
  });

4. 遇到的问题以及解决方式

4.1 原本样式是直接将数字展示上去(如 : 31 ,业务希望展示的是 31%)

可以在 detail 的 formatter 配置项中配置期望的格式

    detail: {
      valueAnimation: true,
      formatter: '{value}%'
    },

4.2 页面初始化图表组件渲染的时候没数据导致页面中显示的是 undefined

会在下面展示数字的位置显示出大大的 undefined 字样
在这里插入图片描述
因为这个数据是从后端获取的,当响应数据没回来的时候会出大大的 undefined 字样,这样子页面也太不友好了,所以
希望当数据还没有回来的时候这里展示的是加载中的字样,当数据返回,再展示真实的百分比数据
在官方文档中可以看到 series-gauge.data.detail. formatter可以是 格式化函数或者字符串
在这里插入图片描述所以这里放进去一个函数

detail: {
   valueAnimation: true,
   formatter: function (value) {
     if (!value) {
       return '加载中';
     } else {
       return value + '%';
     }
   },
   fontSize: 20, // 这里是为了调整百分比字体的大小的
 },

4.3 echarts 图表初始不渲染,代码改变之后才渲染

图表的数据是父组件请求回来数据之后传过来的,但是传过来之后图表却没有渲染,发现代码改动重新保存后才会开始渲染(就是图表的动画才开始动起来)
在网上找到了一个有效的方式是在使用这个图表子组件的位置加上下面的这个 v-if
在这里插入图片描述
原因分析

这是和父子组件的生命周期有关系
以下来自大佬 喜欢星期六_ 的分析
在这里插入图片描述
可以看到在父组件mounted之前, 子组件已经挂载完毕, 引入情景就是无论你封装的 echarts子组件的渲染是放在 mounted() 还是 nextTick 中, 此时你父组件中的 mounted() 还未执行【因为我把数据请求都放在mounted中了】,所以此时渲染的 echarts是没有数据的,或者说你传过去的是空的数据, 就算你的options 中存在部分配置,可数据为空, 图表就会是空白,但是其实你去控制台去审查元素, canvas 标签是有的。

综上: 这种情况下你可以 通过 v-if 去判断, 当确实请求到数据,后再去传给子组件后渲染图表。

或者你也可以到 vue3 setup 中直接发请求【vue3 中 setup 所处生命周期为 beforeCreated 和 created 间, 这两个生命周期是位于子组件之前的】 或者 在 vue2 created() {} 中去发请求, 估计可以不需要 v-if 就可以 渲染出图表。

直接到 vue3 setup 中直接发请求可以成功渲染,不需要v-if,只是组件会需要使用 《suspense》 包裹。

以上,踩坑记录!!!


总结

上次使用 echarts 还是在上次 , 好久好久好久了啊,这次上来就 vben vue3 ts 就懵逼了,但是叭使用方式还都是大体一样的,就此记录 ~ 晚安

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐