如何从API获取数据以在Vuejs中使用chartjs显示图表

问题描述 投票:0回答:3

我是 Vuejs 新手,我想知道如何从 API 获取数据来显示图表。

下面是我的代码,我使用数据作为“日期和挑战”并直接向其提供数据,但现在我想调用我的 API 并将其中的数据提供给“日期和挑战”。

我用它来显示没有 API 的图表的代码:

<template>
  <canvas id="mychart" width="550" height="300"></canvas>
</template>

<script>

export default {
  name: 'Chart',
  data: () => ({
    date: [
      1600934100.0,
      1602009600.0,
      1602747060.0,
      1603050158.390939,
      1603305573.992575
    ],
    challenge: [
      9.0,
      9.5,
      2.5,
      11.52,
      12.4
    ]
  }),
  mounted () {
    // eslint-disable-next-line no-unused-vars
    const data = this.date.map((date, index) => ({
      x: new Date(date * 1000),
      y: this.challenge[index]
    }))

    const ctx = document.getElementById('mychart').getContext('2d')
    // eslint-disable-next-line no-undef,no-unused-vars
    const Chart_2 = new Chart(ctx, {
      type: 'line',
      data: {
        datasets: [
          {
            data,
            label: 'Chart from API ',
            borderColor: '#7367F0'
          }
        ]
      },
      options: {
        scales: {
          xAxes: [
            {
              type: 'time',
              time: {
                unit: 'month',
                displayFormats: {
                  month: 'MMM YYYY'
                }
              }
            }
          ],
          yAxes: [
            {
              ticks: {
                // eslint-disable-next-line no-unused-vars
                callback (value, index, values) {
                  return `${value  }%`
                }
              }
            }
          ]
        }
      }
    })
  }
}
</script>

我知道要获取 API,我们使用 'axios' 或 'fetch' ,所以每当我获取 API 并执行 console.log(response.data) 时,我都会在浏览器的控制台中获取数据,但进一步我不知道对其进行映射并使用这些数据来提供“日期和挑战”以显示图表。

这是我的API:

我的 API,其中包含数据:

https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs

请有人帮助我在代码中使用 API 来显示图表。

vue.js chart.js linechart
3个回答
2
投票

你尝试过这样的吗?

解决方案1

添加

async/await
,这样它将等待数据填充到
data
challege

async mounted () {
    let result = await axios.get('https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs')
    this.date = result.data.date
    this.challenge = result.data.challenge

    // eslint-disable-next-line no-unused-vars
    const data = this.date.map((date, index) => ({
      x: new Date(date * 1000),
      y: this.challenge[index]
    }))

    const ctx = document.getElementById('mychart').getContext('2d')
    // eslint-disable-next-line no-undef,no-unused-vars
    const Chart_2 = new Chart(ctx, {
      type: 'line',
      data: {
        datasets: [
          {
            data,
            label: 'Chart from API ',
            borderColor: '#7367F0'
          }
        ]
      },
      options: {
        scales: {
          xAxes: [
            {
              type: 'time',
              time: {
                unit: 'month',
                displayFormats: {
                  month: 'MMM YYYY'
                }
              }
            }
          ],
          yAxes: [
            {
              ticks: {
                // eslint-disable-next-line no-unused-vars
                callback (value, index, values) {
                  return `${value  }%`
                }
              }
            }
          ]
        }
      }
    })
  }

或者以另一种方式,您可以从其他组件中的 API 获取数据并将

date
challege
作为 props 发送到该组件。

解决方案2

我假设你有图表组件

chart.vue

图表.vue

<template>
  <canvas id="mychart" width="550" height="300"></canvas>
</template>

<script>

export default {
  name: 'Chart',

  props: ['date', 'challenge],

  data: () => ({

  }),
  mounted () {
    // eslint-disable-next-line no-unused-vars
    const data = this.date.map((date, index) => ({
      x: new Date(date * 1000),
      y: this.challenge[index]
    }))

    const ctx = document.getElementById('mychart').getContext('2d')
    // eslint-disable-next-line no-undef,no-unused-vars
    const Chart_2 = new Chart(ctx, {
      type: 'line',
      data: {
        datasets: [
          {
            data,
            label: 'Chart from API ',
            borderColor: '#7367F0'
          }
        ]
      },
      options: {
        scales: {
          xAxes: [
            {
              type: 'time',
              time: {
                unit: 'month',
                displayFormats: {
                  month: 'MMM YYYY'
                }
              }
            }
          ],
          yAxes: [
            {
              ticks: {
                // eslint-disable-next-line no-unused-vars
                callback (value, index, values) {
                  return `${value  }%`
                }
              }
            }
          ]
        }
      }
    })
  }
}
</script>

并在其他组件中导入您的 chart.vue

<template>
    <div>
        <Chart v-if="!isLoading" :date="date" :challenge="challenge" />
    </div>
</template>

<script type="text/javascript">
    import Chart from 'PATH TO chart.vue'
    export default {
        components: {
            Chart
        },
        data () => ({
            date: [],
            challenge: [],
            isLoading: false
        }),
        methods: {
            async getData () {
                this.isLoading = true
                let result = await axios.get(API URL)
                this.date = result.data.date
                this.challenge = result.data.challenge
                this.isLoading = false
            }
        },
        mounted () {
            this.getData()
        }
    }
</script>

chart.vue 中,从

date
中删除
challege
data
,因为您将拥有
props
,为了最佳实践,
props
data
不能具有相同的属性名称。

在导入 chart.vue 的其他组件中,只需照常获取数据即可。

我在项目中使用chartjs时所做的事情,我总是在 中添加

v-if
,它会让axios先获取数据,然后重新挂载图表组件。因为我猜chartjs 对 vuejs 数据更改没有反应,所以需要先更新数据然后再次重新挂载。


0
投票

终于得到答案了万岁!

我正在分享我是如何做到的,甚至你也可以做同样的事情,以便使用 API 数据可视化图表。

<template>
  <div class="chart-container" style="position: relative; height: 25vh; width:100%;">
    <canvas id="DisplayChart" ></canvas>
  </div>
</template>

<script>
import moment from 'moment'
export default {
  name: 'Chart_from_API',
  data () {
    return {
      myChart: []
    }
  },
  async mounted () {
    await this.$http.get('https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs') //Your API has to be given here
      .then((response) => {
        const result = response.data
        const ctx = document.getElementById('DisplayChart').getContext('2d')
        const Chart_data = []
        for (let i = 0; i < result.date.length; i++) {
          Chart_data.push({
            x_axis: moment(result.date[i], 'X').toDate(),  //To Convert Unix Timestamp into Date
            y_axis: result.challenge[i]
          })
        }
        // eslint-disable-next-line init-declarations,prefer-const
        let myChart
        if (myChart !== undefined) {
          myChart.destroy()
        }

        // eslint-disable-next-line no-undef
        myChart = new Chart(ctx, {
          type: 'line',
          data: {
            datasets: [
              {
                label: 'Chart_from_API',
                data: Chart_data,
                borderColor: '#EA5455',
                lineTension: 0
              }
            ]
          },
          options: {
            lineTension: 0,
            maintainAspectRatio: false,
            legend: {
              display: false
            },
            scales: {
              yAxes: [
                {
                  scaleLabel: {
                    display: false
                  },
                  ticks: {
                    beginAtZero: true,
                    // eslint-disable-next-line no-unused-vars
                    callback (value) {
                      return `${value  }k`    // y-axis value will append k to it
                    }
                  }
                }
              ],
              xAxes: [
                {
                  type: 'time',
                  time: {
                    unit: 'month'
                  },
                  scaleLabel: {
                    display: true,
                    labelString: ''
                  }
                }
              ]
            }
          }
        })
      })
      .catch((error) => {
        console.log(error)
      })
  }
}
</script>

0
投票

您可以使用

vue-chartjs
,它是 Vue 中 Chart.js 的包装器。

通过

npm
包管理器安装它。

npm install vue-chartjs chart.js

根据文档,从异步API端点访问数据时存在一个常见问题:

这种方法的问题在于,Chart.js 尝试渲染您的图表并同步访问图表数据,因此您的图表会在 API 数据到达之前安装

为了防止这种情况,简单的

v-if
是最好的解决方案。以下 Vue 组件使用布尔变量在数据到达之前停止图表安装。

<template>
  <div>
    <h1>Stock Data</h1>
    <!-- The v-if is used to conditionally render a block -->
    <Bar id="my-chart-id" v-if="loaded" :options="chartOptions" :data="chartData" :width="600" />
  </div>
</template>

<script>
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)

export default {
  name: 'BarChart',
  components: { Bar },
  data: () => ({
    // Prevents chart to mount before the API data arrives
    loaded: false,
    chartData: {
      labels: [],
      datasets: [
        {
          label: 'My Label',
          data: [],
          backgroundColor: 'rgba(54, 162, 235, 0.2)'
        }
      ]
    },
    chartOptions: {
      responsive: true
    }
  }),
  async mounted() {
    const apiUrl = 'http://localhost:8000/data'

    // Make an HTTP request to fetch the data from the API endpoint
    await fetch(apiUrl)
      .then((response) => response.json())
      .then((data) => {
        // Extract data from the API response and update the chartData
        this.chartData.labels = data.map((stock) => stock.date)
        this.chartData.datasets[0].data = data.map((stock) => stock.value)

        // Allow the chart to display the data from the API endpoint
        this.loaded = true
      })
      .catch((error) => {
        console.error('Error fetching data:', error)
      })
  }
}
</script>

关键是只有数据成功到达才渲染条形图。这是通过将

loaded
变量设置为 true 来实现的。请注意,每当有新数据到达时,您都需要重新加载页面。

© www.soinside.com 2019 - 2024. All rights reserved.