【问题标题】:Vue js + HighChart - how can I make a synchronous axios call before the component get rendered?Vue js + HighChart - 如何在组件渲染之前进行同步 axios 调用?
【发布时间】:2020-03-18 04:12:43
【问题描述】:

亲爱的,我是 vue js 的新手。我制作了一个小 vue js + NUXT 应用程序,它使用 HighCharts 图表呈现。通过 web 服务调用 axios 检索数据。

问题:网络服务调用是异步的,我的图表已经初始化。如何在我的图表呈现之前使调用同步?

虽然 Highchart 本身需要时间来初始化,但我不得不使用它来设置超时功能。如果您忽略这一点,我会遇到在图表初始化时设置数据的问题,这会导致图表显示错误。

<template>
  <div>
  <highcharts :options="chartOptions"></highcharts>
  </div>
</template>
<script>
    import axios from 'axios';
    import {Chart} from 'highcharts-vue'
    import Highcharts3D from 'highcharts/highcharts-3d'
    import Highcharts from 'highcharts'

    if (typeof Highcharts === 'object') {
        Highcharts3D(Highcharts);
    }

    export default {
        layout: 'contentOnly',
        auth: false,
        components: {
            highcharts: Chart
        },
        data() {
            return {
                data: [],
                chartOptions: {
                    title: {
                        text: ''
                    },
                    tooltip: {
                        pointFormat: '{point.percentage:.2f}%',
                    },
                    chart: {
                        type: 'pie',
                        options3d: {
                            enabled: true,
                            alpha: 50,
                        },
                        // plotBackgroundColor: 0,
                        // plotBorderWidth: 0,
                        // plotShadow: true,
                    },
                    series: [{
                        name: '',
                        data: [1],
                        tooltip: {
                            valueDecimals: 0
                        }
                    }],
                    plotOptions: {
                        pie: {
                            allowPointSelect: true,
                            cursor: 'pointer',
                            innerSize: '30%',
                            depth: 100,
                            dataLabels: {
                                enabled: true,
                                percentageDecimals: 2,
                                color: '#002a52',
                                connectorColor: '#002a52',
                                formatter: function () {
                                    return '<b>' + this.point.name + '</b>: ' + this.percentage.toFixed(2) + ' %';
                                }
                            }
                        }
                    },

                    credits: {
                        enabled: false
                    },
                    exporting: {
                        buttons: {
                            printButton: {
                                enabled: false
                            },
                            contextButton: {
                                enabled: false
                            }
                        }
                    },
                }
            };
        },
        mounted() {
            this.fetchData()
            setTimeout(function(){ 
                let data = []
                var index = 0
                for (var key in this.data) {
                    data[index] = []
                    data[index][0] = key
                    if (key == '30') data[index][0] = '< 30'
                    if (key == '999') data[index][0] = '> 65'
                    data[index][1] = this.data[key]
                    index++;
                }
                this.chartOptions.series[0].data = data
           }.bind(this), 1000);
        },
        methods: {
            fetchData() {       
                axios.post(this.$axios.defaults.baseURL + 'api/analytics/age', {
                    locale: this.$i18n.locale,
                    onlyPaid: this.$route.query.onlyPaid
                }).then(response => {
                    this.data = response.data
                }).catch(e => {
                    console.log(e)
                })
            }
        }
    }
</script>

【问题讨论】:

  • 我不明白你什么时候需要在 vue export default 之外放置一个 if。您应该在组件生命周期挂钩中移动它。
  • 如果我保留HighCharts3D(Highcharts) 而没有if,我会收到错误TypeError: Cannot read property 'parts/Globals.js of undefined。根据 Github 上描述的问题,这是一种解决方法,请参阅issue 10588

标签: vue.js highcharts axios nuxt.js


【解决方案1】:

您需要在beforeCreate 钩子中获取数据,将其保存在组件数据中,并使组件渲染依赖于该数据:

<template>
  <div v-if="chartOptions.series[0].data.length">
    <highcharts class="hc" :options="chartOptions" ref="chart"></highcharts>
  </div>
</template>

<script>
export default {
  beforeCreate() {
    fetch("https://api.myjson.com/bins/hj6se")
      .then(resp => resp.json())
      .then(resp => {
        this.chartOptions.series[0].data = resp;
      });
  },

  data() {
    return {
      chartOptions: {
        series: [{
          data: []
        }]
      }
    };
  }
};
</script>

现场演示: https://codesandbox.io/s/highcharts-vue-demo-nekm0

【讨论】:

    猜你喜欢
    • 2021-12-09
    • 2019-01-27
    • 2021-09-05
    • 2019-01-03
    • 2019-12-24
    • 2021-06-01
    • 2018-11-08
    • 1970-01-01
    • 2019-11-18
    相关资源
    最近更新 更多