我是 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 来显示图表。
你尝试过这样的吗?
解决方案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 数据更改没有反应,所以需要先更新数据然后再次重新挂载。
终于得到答案了万岁!
我正在分享我是如何做到的,甚至你也可以做同样的事情,以便使用 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>
您可以使用
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 来实现的。请注意,每当有新数据到达时,您都需要重新加载页面。