Как обрабатывать асинхронные данные с помощью vue-echarts?

Я использую vue-echarts вместе с Apache eCharts.

Но я не знаю, как загрузить значения асинхронных данных.

Я просмотрел примеры в документации и до сих пор не могу понять.

Может ли кто-нибудь взглянуть на этот SFC и сказать мне, как обновить значение data внутри ссылки gaugeOption?

В настоящее время массив gaugeData загружается со значением 0 и остается таким, хотя props.totalScore обновляется новым значением.

<template>
    <vue-echarts
        class="echart-container"
        autoresize
        :option="gaugeOption"
    />
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';

const props = defineProps({
  totalScore: {
    type: Number,
    required: true,
  },
  reportDate: {
    type: String,
    required: true,
  },
});

const gaugeData = [
  {
    value: props.totalScore,
  },
];

const gaugeOption = ref({
  series: [
    {
      emphasis: {
        disabled: true,
      },
      data: gaugeData,
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      min: 0,
      max: 100,
      splitNumber: 3,
      radius: '95%',
      center: ['50%', '95%'],
      pointer: {
        icon: 'circle',
        length: '12%',
        width: 50,
        offsetCenter: [0, '-90%'],
        itemStyle: {
          color: '#FFFFFF',
          borderColor: scoreHexColor,
          borderWidth: 5,
          shadowColor: 'rgba(10, 31, 68, 0.5)',
          shadowBlur: 2,
          shadowOffsetY: 0.1,
        },
      },
      axisLine: {
        show: true,
        roundCap: true,
        lineStyle: {
          width: 10,
          color: [
            [0.48, '#ee6352'],
            [0.52],
            [0.66, '#ff8b3b'],
            [0.7],
            [0.83, '#fac05e'],
            [0.87],
            [1, '#59cd90'],
          ],
        },
      },
      axisTick: {
        length: 2,
        lineStyle: {
          color: '#8a94a6',
          width: 2,
        },
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        show: false,
      },
      title: {
        show: false,
      },
      detail: {
        rich: {
          header: {
            fontSize: 36,
            fontWeight: 700,
            fontFamily: 'Open Sans',
            color: '#0a1f44',
          },
          subHeader: {
            fontSize: 16,
            fontWeight: 400,
            fontFamily: 'Open Sans',
            color: '#8a94a6',
          },
        },
        formatter: (value: number) => {
          return `{header|${value}}\n{subHeader|${props.reportDate}}`;
        },
        offsetCenter: [0, '-20%'],
        valueAnimation: true,
      },
    },
  ],
});
</script>

<style lang="scss" scoped>
.echart-container {
  height: 300px;
  max-width: 300px;
  margin-top: -135px;
}
</style>

ИЗМЕНИТЬ ОБНОВЛЕНИЕ:

Теперь я могу правильно загрузить диаграмму, используя еще один ref и watch реквизита.

Но когда реквизит меняется, он рисует новый номер ПОВЕРХ старого. Но он мне нужен для замены старого номера.

Посмотрите, как это выглядит при загрузке страницы (это правильно):

И посмотрите, как это выглядит, когда я пытаюсь изменить значение gaugeDataRef (это неправильно, значение рисуется поверх старого):

Вот обновленный код:

import { computed, ref, watch } from 'vue';

const props = defineProps({
  totalScore: {
    type: Number,
    required: true,
  },
  reportDate: {
    type: String,
    required: true,
  },
});

const gaugeDataRef = ref<number[]>([]);

watch(props, () => {
  gaugeDataRef.value.slice(0, 1);
  gaugeDataRef.value.push(props.totalScore);
});

const gaugeOption = ref({
  series: [
    {
      emphasis: {
        disabled: true,
      },
      data: gaugeDataRef.value,
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      min: 0,
      max: 100,
      splitNumber: 3,
      radius: '95%',
      center: ['50%', '95%'],
      pointer: {
        icon: 'circle',
        length: '12%',
        width: 50,
        offsetCenter: [0, '-90%'],
        itemStyle: {
          color: '#FFFFFF',
          borderColor: scoreHexColor,
          borderWidth: 5,
          shadowColor: 'rgba(10, 31, 68, 0.5)',
          shadowBlur: 2,
          shadowOffsetY: 0.1,
        },
      },
      axisLine: {
        show: true,
        roundCap: true,
        lineStyle: {
          width: 10,
          color: [
            [0.48, '#ee6352'],
            [0.52],
            [0.66, '#ff8b3b'],
            [0.7],
            [0.83, '#fac05e'],
            [0.87],
            [1, '#59cd90'],
          ],
        },
      },
      axisTick: {
        length: 2,
        lineStyle: {
          color: '#8a94a6',
          width: 2,
        },
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        show: false,
      },
      title: {
        show: false,
      },
      detail: {
        rich: {
          header: {
            fontSize: 36,
            fontWeight: 700,
            fontFamily: 'Open Sans',
            color: '#0a1f44',
          },
          subHeader: {
            fontSize: 16,
            fontWeight: 400,
            fontFamily: 'Open Sans',
            color: '#8a94a6',
          },
        },
        formatter: (value: number) => {
          return `{header|${value}}\n{subHeader|${props.reportDate}}`;
        },
        offsetCenter: [0, '-20%'],
        valueAnimation: true,
      },
    },
  ],
});

Ваш код слишком длинный, поэтому нам трудно помочь. Попробуйте сузить проблему

Duannx 11.11.2022 11:26

@Duannx Я сократил код, чтобы включить только диаграмму

TinyTiger 11.11.2022 12:53

Если он говорит использовать ref, почему вы передаете туда такие сложные объекты?

Mises 11.11.2022 16:05

@Mises Ты спрашиваешь о gaugeOption? Это стандартный объект параметров, который следует за документацией vue-echarts. Если вы видите документы, на которые я ссылался в вопросе, вы увидите, что они также заключают объект параметров в ref.

TinyTiger 11.11.2022 16:15
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
4
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Догадаться.

Мне нужно было добавить watch к props, который сначала очищает массив, а затем добавляет новое значение обратно в массив.

import { computed, ref, watch } from 'vue';

const props = defineProps({
  totalScore: {
    type: Number,
    required: true,
  },
  reportDate: {
    type: String,
    required: true,
  },
});

const gaugeDataRef = ref<number[]>([]);

watch(props, () => {
  gaugeDataRef.value.slice(0, 1);
  gaugeDataRef.value.push(props.totalScore);
});

const gaugeOption = ref({
  series: [
    {
      emphasis: {
        disabled: true,
      },
      data: gaugeDataRef.value,
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      min: 0,
      max: 100,
      splitNumber: 3,
      radius: '95%',
      center: ['50%', '95%'],
      pointer: {
        icon: 'circle',
        length: '12%',
        width: 50,
        offsetCenter: [0, '-90%'],
        itemStyle: {
          color: '#FFFFFF',
          borderColor: scoreHexColor,
          borderWidth: 5,
          shadowColor: 'rgba(10, 31, 68, 0.5)',
          shadowBlur: 2,
          shadowOffsetY: 0.1,
        },
      },
      axisLine: {
        show: true,
        roundCap: true,
        lineStyle: {
          width: 10,
          color: [
            [0.48, '#ee6352'],
            [0.52],
            [0.66, '#ff8b3b'],
            [0.7],
            [0.83, '#fac05e'],
            [0.87],
            [1, '#59cd90'],
          ],
        },
      },
      axisTick: {
        length: 2,
        lineStyle: {
          color: '#8a94a6',
          width: 2,
        },
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        show: false,
      },
      title: {
        show: false,
      },
      detail: {
        rich: {
          header: {
            fontSize: 36,
            fontWeight: 700,
            fontFamily: 'Open Sans',
            color: '#0a1f44',
          },
          subHeader: {
            fontSize: 16,
            fontWeight: 400,
            fontFamily: 'Open Sans',
            color: '#8a94a6',
          },
        },
        formatter: (value: number) => {
          return `{header|${value}}\n{subHeader|${props.reportDate}}`;
        },
        offsetCenter: [0, '-20%'],
        valueAnimation: true,
      },
    },
  ],
});
import { computed, ref, watch } from 'vue';

const props = defineProps({
  totalScore: {
    type: Number,
    required: true,
  },
  reportDate: {
    type: String,
    required: true,
  },
});

const gaugeDataRef = ref<number[]>([]);

watch(props, () => {
  gaugeDataRef.value.slice(0, 1);
  gaugeDataRef.value.push(props.totalScore);
});

const gaugeOption = ref({
  series: [
    {
      emphasis: {
        disabled: true,
      },
      data: gaugeDataRef.value,
      type: 'gauge',
      startAngle: 180,
      endAngle: 0,
      min: 0,
      max: 100,
      splitNumber: 3,
      radius: '95%',
      center: ['50%', '95%'],
      pointer: {
        icon: 'circle',
        length: '12%',
        width: 50,
        offsetCenter: [0, '-90%'],
        itemStyle: {
          color: '#FFFFFF',
          borderColor: scoreHexColor,
          borderWidth: 5,
          shadowColor: 'rgba(10, 31, 68, 0.5)',
          shadowBlur: 2,
          shadowOffsetY: 0.1,
        },
      },
      axisLine: {
        show: true,
        roundCap: true,
        lineStyle: {
          width: 10,
          color: [
            [0.48, '#ee6352'],
            [0.52],
            [0.66, '#ff8b3b'],
            [0.7],
            [0.83, '#fac05e'],
            [0.87],
            [1, '#59cd90'],
          ],
        },
      },
      axisTick: {
        length: 2,
        lineStyle: {
          color: '#8a94a6',
          width: 2,
        },
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        show: false,
      },
      title: {
        show: false,
      },
      detail: {
        rich: {
          header: {
            fontSize: 36,
            fontWeight: 700,
            fontFamily: 'Open Sans',
            color: '#0a1f44',
          },
          subHeader: {
            fontSize: 16,
            fontWeight: 400,
            fontFamily: 'Open Sans',
            color: '#8a94a6',
          },
        },
        formatter: (value: number) => {
          return `{header|${value}}\n{subHeader|${props.reportDate}}`;
        },
        offsetCenter: [0, '-20%'],
        valueAnimation: true,
      },
    },
  ],
});

Другие вопросы по теме