【问题标题】:Initialize a Chart.js chart with data from an api使用来自 api 的数据初始化 Chart.js 图表
【发布时间】:2021-05-28 07:07:19
【问题描述】:

正如我在标题中提到的,我想使用 api 初始化 Chart.js 图表。我找到了教程,但它们大多在呈现页面后更新数据。我想在页面呈现之前更新图表。所以我直接看到初始化图表没有重新加载。

<template>
    <h3>Stacked</h3>
    <Chart type="bar" v-if="isReady" :data="stackedData" :options="stackedOptions"/>
</template>

<script>
import axios from "axios";
import {defineComponent, ref} from 'vue';
export default {
 
    data()  {  
 
       return {
              isReady: false,
              stackedData: {
                labels: ['A', 'B', 'C', 'D'],
                datasets: [{
                    type: 'bar',
                    label: 'Something',
                    backgroundColor: '#42A5F5',
                    data: this.list_all
                }, {
                    type: 'bar',
                    label: 'Another',
                    backgroundColor: '#66BB6A',
                    data: this.list_intersection
                }]
            },
           
            stackedOptions: {
                tooltips: {
                    mode: 'index',
                    intersect: false
                },
                responsive: true,
                scales: {
                    xAxes: [{
                        stacked: true,
                    }],
                    yAxes: [{
                        stacked: true
                    }]
                }
            },
            basicOptions: null,

//---------------------------------------------------
            all:[]
            list_intersection:[],
            list_all:[]
        }    
    },

    beforeCreate() {
            let apiKaderURL = 'http://localhost:4000/apiKader';
            axios.get(apiKaderURL).then(res => {

                this.all = res.data;
                this.saveData()
                this.isReady=true;
            }).catch(error => {
                console.log(error)
            });
        },

     methods:{
       saveData: function (){
          
          for (var i in this.all){
                if(this.all[i].id==='2' ){
                    this.list_all.push(this.all[i].someNumber)
                }
                if(this.all[i].id==='8'){
                    this.list_intersection.push(this.all[i].someNumber) 
                }                     
           }
           return this.list_all && this.list_intersection
       }
    }
}
</script>


我只是尝试使用 axios 获取值,过滤它们,然后将它们返回到图表对象的数据属性,以便使用这些值进行初始化。

我想,因为我调用了beforeCreate,它应该可以工作,因为我在渲染之前初始化了值但是图表没有显示任何值。

我也尝试过使用vue-chartjs,但我认为它不能真正使用 Vue 3,或者我做错了什么。

我怎样才能做到这一点? 非常感谢您。

【问题讨论】:

  • 如果v-if 没有帮助,问题不在于(a)同步性。你能显示&lt;chart&gt; 组件吗?
  • 我只是将它导入到 main.js 中,正如这里提到的 primefaces.org/primevue/showcase/#/chart 。我必须自己定义组件吗?
  • 请检查这个 GiHub 问题页面github.com/apertureless/vue-chartjs/issues/379chartJS 对数据更改没有反应
  • @FilipKováč 好的,谢谢。我认为正如这里提到的stackoverflow.com/questions/64114215/… 库现在似乎不支持 vue 3。我之前也尝试过使用它,但我遇到了很多问题。有其他选择吗?
  • 如果您能够从 Primevue 文档中获取示例,那么您的代码也没有明显的理由不应该与 v-if 一起使用,除非某些数据/选项格式不正确。跨度>

标签: javascript vue.js chart.js vue-component vuejs3


【解决方案1】:

生命周期钩子(如beforeCreate 等)实际上不会延迟后续组件生命周期步骤,即使是异步的,它们只是提供运行代码的入口点。

使用v-if 延迟图表的呈现,直到数据准备好。 v-if 就像 watch 一样,在此之前根本不会渲染图表。使用 isReady 变量,您将在数据完成保存时设置该变量:

<Chart type="bar" v-if="isReady" :data="stackedData" :options="stackedOptions"/>
data()  {  
  return {
    isReady: false,
    ...
  }
}
axios.get(apiKaderURL).then(res => {
  this.all = res.data;
  this.saveData()
  this.isReady = true;  // Triggering the `v-if`
})

(未经测试,但原则上应该可以工作)


此外,您不能使用this 从另一个数据属性设置数据属性,它将是undefined。您可以将它们设置为null:

data: this.list_all  // Does nothing, can't use `this` like that
data: null           // Change to this

因此将其设置为null 并修复saveData 方法:

methods: {
  saveData() {
    const listAll = [];
    const listIntersection = [];

    for (var i in this.all){
      if(this.all[i].id==='2' ){
        listAll.push(this.all[i].someNumber)
      }
      if(this.all[i].id==='8'){
        listIntersection.push(this.all[i].someNumber) 
      }                     
    }
   
    this.stackedData.datasets[0].data = listAll;
    this.stackedData.datasets[1].data = listIntersection;
  }
}

【讨论】:

    【解决方案2】:

    我之前没有使用过 Chart.js,但我通读了安装、集成和使用文档并提出了一个可能对您有所帮助的示例(带有 Vue CLI 的 Vue 2)。

    我使用我的 App.vue SFC 作为子图表组件 ChartTest.vue 的父级。在父级中,我使用“mounted”挂钩中的“setTimeout”调用模拟了 API 调用延迟。

    App.vue

    <template>
      <div id="app">
        <chart-test v-if="dataReady" :chartData="chartData" />
      </div>
    </template>
    
    <script>
      import ChartTest from '@/components/ChartTest'
    
      export default {
        name: 'App',
        components: {
          ChartTest
        },
        data() {
          return {
            chartData: [12, 19, 3, 5, 2, 3],
            dataReady: false
          }
        },
        methods: {
          getData() {
            this.dataReady = true;
          }
        },
        mounted() {
          // Simulate API call
          setTimeout(this.getData(), 2000);
        }
      }
    </script>
    

    ChartTest.vue

    <template>
      <div class="chart-test">
        <h3>Chart Test</h3>
        <canvas id="my-chart" width="400" height="400" ref="chartref"></canvas>
      </div>
    </template>
    
    <script>
      import Chart from 'chart.js';
    
      export default {
        data() {
          return {
            myChart: null
          }
        },
        props: {
          chartData: {
            type: Array,
            required: true
          }
        },
        mounted() {
          this.myChart = new Chart(this.$refs.chartref, {
            type: 'bar',
            data: {
              labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
              datasets: [{
                label: '# of Votes',
                data: this.chartData,
                backgroundColor: [
                  'rgba(255, 99, 132, 0.2)',
                  'rgba(54, 162, 235, 0.2)',
                  'rgba(255, 206, 86, 0.2)',
                  'rgba(75, 192, 192, 0.2)',
                  'rgba(153, 102, 255, 0.2)',
                  'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                  'rgba(255, 99, 132, 1)',
                  'rgba(54, 162, 235, 1)',
                  'rgba(255, 206, 86, 1)',
                  'rgba(75, 192, 192, 1)',
                  'rgba(153, 102, 255, 1)',
                  'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
              }]
            },
            options: {
              scales: {
                yAxes: [{
                  ticks: {
                    beginAtZero: true
                  }
                }]
              }
            }
          });
        }
      }
    </script>
    

    【讨论】:

    • 感谢您花时间解决我的问题。我玩了一点,这也解决了我的问题:-)
    猜你喜欢
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    相关资源
    最近更新 更多