Chart JS 不会使用 update() 方法动态更新新数据

Chart JS isn't dynamically updating with new data with update() method

我在我的 Nuxt JS 项目中使用 Chart JS 和 Vue Chart JS 包装器。出于某种原因,尽管有新数据,但我的图表没有更新新数据。我的图表设置有一个名为 LineChart.vue 的组件,以及一个名为 LineChart.js 的插件,位于我的 plugins 目录中。

我的组件看起来像:

<template>
  <div>
    <line-chart :chart-data="customChartData" class="data-chart"></line-chart>
  </div>
</template>

<style>
.data-chart canvas {
  width: 100% !important;
  height: auto !important;
}
</style>

<script>
import LineChart from '~/plugins/LineChart.js'
export default {
  components: {
    LineChart
  },
  props: {
    chartKey: {
      type: Number,
      default: 0
    },
    groupBy: {
      type: String,
      default: 'hourly'
    },
    labels: {
      type: Array,
      default: null
    },
    datasets: {
      type: Array,
      default: null
    },
    options: {
      type: Object,
      default: () => ({})
    }
  },
  data () {
    return {
      customChartData: {}
    }
  },
  mounted () {
    this.fillData()
  },
  methods: {

    /*
    ** Fill data
    */
    fillData () {

      const labelsToUse = []
      const labels = this.labels
      const first = labels[0]
      const last = labels[labels.length - 1]
      let diff = 0

      for (const [index, label] of labels.entries()) {
        const periodStart = this.$dayjs(Date.parse(first))
        const periodFinish = this.$dayjs(Date.parse(last))
        diff = periodFinish.diff(periodStart, 'day', true)

        if (!diff) {
          labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format('MMM Do'))
        }

        labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format(`${diff > 1 ? 'MMM Do' : 'HH:mm'}`))
      }

      this.customChartData = {
        labels: labelsToUse,
        datasets: this.datasets,
        options: this.options
      }
    }

  }
}
</script>

我的插件看起来像...

import { Line, mixins } from 'vue-chartjs'
import _ from 'lodash';
const { reactiveProp } = mixins

export default {
  extends: Line,
  mixins: [reactiveProp],
  data () {
    return {
      options: {
        responsive: true,
        maintainAspectRatio: false,
        legend: {
          display: false
        },
        scales: {
          yAxes: [{
            gridLines: {
              display: true,
              color: '#eceaea'
            },
          }],
          xAxes: [{
            gridLines: {
              display: false
            },
            ticks: {
              autoSkip: true,
              maxTicksLimit: window.innerWidth < 575 ? 2.1 : 4.1,
              maxRotation: 0,
              minRotation: 0
            }
          }]
        },
        elements: {
          point: {
            radius: 0,
            hitRadius: 35
          }
        }
      }
    }
  },
  mounted () {
    this.renderLineChart()
  },
  methods: {

    /*
    ** Get chart options
    */
    getChartOptions () {
      return this.options
    },

    /*
    ** Render a line chart
    */
    renderLineChart () {
      const options = this.getChartOptions()

      // this.chartdata is created in the mixin.
      // If you want to pass options please create a local options object
      this.renderChart(this.localData, options)
    }

  },
  computed: {
    localData: function() {
      return this.chartData
    }
  },
  watch: {
    chartData: {
      handler: function (val, oldVal) {
        const options = this.getChartOptions()
        const clone = _.cloneDeep(this.localData)

        console.log(this.localData)
        this._data._chart.update()
        this.renderChart(clone, options)
      },
      deep: true
    }
  }
}

当我在我的插件的 watch 方法中记录 console.log(this.localData) 时,我没有看到我的 labels 更新了从 :labels="server[Object.keys(server)[0]].history.labels" 推送的新标签和数据在我调用折线图的网页内,我缺少什么?

调用我的图表组件的页面是:

<div class="col-span-12" v-for="(server, index) in servers" :key="index">
  <div class="bg-white p-6 rounded-md">
    <h3 class="text-md font-medium text-gray-900">{{ server[Object.keys(server)[0]].agent.agent }}</h3>
  </div>
  <hr v-if="server[Object.keys(server)[0]].history" />
  <div v-if="server[Object.keys(server)[0]].history" class="bg-white p-6 rounded-md">
    <h3 class="text-md font-medium text-gray-500 mb-3">Free memory</h3>
    <div class="chart chart--generic">
      <LineChart
        :labels="server[Object.keys(server)[0]].history.labels"
        :datasets="[{
          fill: false,
          borderWidth: 2.5,
          pointBackgroundColor: '#fff',
          borderColor: '#5046e5',
          data: server[Object.keys(server)[0]].history.data,
        }]"
      />
    </div>
  </div>
</div>

更新数组标签后,您可以尝试调用 fillData() 方法。

希望有用

我目前正在构建一个应用程序并使用 Nuxt 和 ApexCharts 并且遇到了非常相似的问题。我的数据正在更新,但我在图表中没有看到任何变化。我解决这个问题的方法是向我的图表组件添加一个 key 并手动强制它重新呈现。 Vue 使用 key 属性来跟踪已更改和未更改的内容。通过提供一个新的,我们强制重新渲染。

我的解决方案的一个例子是,

<apexcharts
  v-if="chartOptions"
  :id="chartId"
  :key="key"
  class="am2-utility-chart"
  :class="[isCategoryType ? 'marginLeft' : '']"
  :ref="chartId"
  :width="chartOptions.chart.width"
  :height="chartOptions.chart.height"
  :type="chartOptions.type"
  :options="chartOptions"
  :series="series"
/>

其中 key 是字符串类型的道具,我通过执行辅助函数从父级生成新密钥,

export function generateRandomString(value) {
  let r = Math.random().toString(36).substring(7)

  if (!value) return r
  return `${value}_${r}`
}

*上面函数中的 value 参数是可选的。我传递图表名称是为了给键更多上下文。

如果有帮助请告诉我,我很想听听。