Chart.js not rendering properly until window resiz

2019-07-29 11:30发布

I'm trying to make an app to graph tide data using vue.js and chart.js.

I get my data from the Wunderground API using axios, format it for chart.js, then pass it using props to a component to graph it. However, when I initially load the page, a blank chart loads. Upon resizing the window, or toggling the dataset the data appears properly.

I've read Chart.js will not render using vue.js until window resizes, which describes a similar problem, but unlike in that question, my canvas renders properly. The problem is only the dataset.

I've tried passing data through the props without using the API, and it works fine.

LineChart component

export default {
  name: 'LineChart',
  props: ['data', 'options'],
  mounted() {
    let ctx = document.getElementById('chart').getContext('2d')
    let chart = new Chart(ctx, {
        type: 'line',
        data: this.data,
        options: this.options
    })
  }
}

App component

export default {
  name: 'app',
  data() {
    return {
      url: 'http://api.wunderground.com/api/f219964b4d6ec312/tide/q/autoip.json',
      chartData: {
        labels: [],
        datasets: [
          {
            label: 'Tide',
            data: []
          }
        ]
      },
      chartOptions: {
        responsive: true,
        scales: {
          xAxes: [{
            type: 'time',
          }]
        }
      }
    }
  },
  components: {
    LineChart
  },
  created() {
    this.getWeatherData()
  },
  methods: {
    getWeatherData() {
      axios.get(this.url).then((response) => {
        response.data.tide.tideSummary.filter(this.isTideData).forEach((obj) => {
          let d = new Date(0)
          d.setUTCSeconds(obj.date.epoch)
          this.chartData.labels.push(d)
          this.chartData.datasets[0].data.push(parseFloat(obj.data.height))
        })
      })
    },
    isTideData(obj) {
      return (obj.data.type == "Low Tide" || obj.data.type == "High Tide")
    }
  }
}

What am I doing wrong?

1条回答
ら.Afraid
2楼-- · 2019-07-29 12:30

Like the question you linked here, it's probably another problem caused by async loading. You're doing the new Chart(...) in the child component's mounted, by which time the data prop is probably still empty (on its way from the api url). Try removing the mounted and adding a watch like this:

data() {
    return {
        loaded: false
    };
},
watch: {
    data: function (newVal, oldVal) {
        if (newVal.length>0 && !this.loaded) {
            this.loaded = true;
            new Chart(...);
        }
    }
}

I added a loaded flag here to make sure we only init the chart once, since it automatically adjusts to resizes, etc.

查看更多
登录 后发表回答