【问题标题】:Chart.js will not render using vue.js until window resizes在调整窗口大小之前,Chart.js 不会使用 vue.js 渲染
【发布时间】:2016-11-27 22:27:42
【问题描述】:

我有一个使用 Bootstrap、vue.js 和 chart.js 的简单应用。 HTML 模板非常简单。在搜索我的错误时,我注意到这个问题通常是在尝试在选项卡或模式中呈现图表时引起的,但我的图表没有在模式或选项卡中。

只要我调整浏览器窗口的大小,图表就会正确呈现并缩放以适应 div 和所有内容。

无论出于何种原因,当页面首次加载时,canvas HTML 标签呈现如下:

<canvas id="graph" width="0" height="0" style="margin: auto; width: 0px; display: block; height: 0px;"></canvas>

但是当我调整窗口大小时,一切都改变了,我可以正确地看到图表。

<canvas id="graph" width="493" height="328" style="margin: auto; width: 493px; display: block; height: 328px;"></canvas>

为什么页面加载时高度和宽度不正确?

HTML 模板

<div class="panel panel-default">
      <div class="panel-heading">Chart List</div>
      <div class="panel-body">
        <div class="row">
            <div class="col-sm-6">
                <defaultchart>
                </defaultchart>
            </div>
            <div class="col-sm-6">
                <chartlistview
                    :data="{{ $private }}"
                    :columns="{{ json_encode($columns) }}"
                >
                </chartlistview>
            </div>
        </div>
            </div>
    </div>

DefaultChart.vue

<template>
  <div>
    <canvas 
      id="graph" 
      v-el:canvas 
      width="600" 
      height="400" 
      style="margin:auto; width: 600px;"
    ></canvas>
  </div>
</template>

<script>
  export default {

    data() {
      return {
        ourChart: '',
        chartData: {
          labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
          datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3]
          }]
        }
      };
    },

    ready() {

      this.drawChart();     
    },

    methods: {

      drawChart: function() {

        if (this.ourChart) {
          this.ourChart.destroy();
        }
        var context = document.querySelector('#graph').getContext('2d');
        this.ourChart = new Chart(context, {
          type: 'line',
          data: this.chartData
          // wouldn't render at all with this regardless of resizing
          /*options: {
            response: true,
            maintainAspectRatio: false
          }*/
        });

        // added these lines to see if it would fix the issue; it didn't
        this.ourChart.render();
        this.ourChart.update();
      }

    }
  };
</script>

【问题讨论】:

    标签: twitter-bootstrap-3 chart.js vue.js


    【解决方案1】:

    ready() 中访问 DOM 很棘手,因为 Vue 异步更新 DOM,因此更改可能尚未完全应用,和/或浏览器尚未完成新布局。

    使用$nextTick() 推迟到更新完成:

    ready() {
      this.$nextTick(function() {
        this.drawChart();     
      })
    },
    

    通常在这些情况下可以解决问题,至少在 Vue 方面。关于chart.js的配置不能多说。

    【讨论】:

    • 哇,成功了。谢谢!问题虽然。这是Vue中的错误吗?我认为ready() 方法可以像在jQuery 中一样工作。还是我用错了,我应该一直用$nextTick
    • 不,这不是 Vue 中的错误。正如我所说,Vue updates the DOM asynchronously 出于性能原因,这意味着当 Vue 说“将这个元素放入 DOM”,然后触发 ready() 钩子时,“这个元素”可能还没有在 DOM 中。由于这是人们似乎遇到的最常见的陷阱之一,因此我建议将其添加到文档中更显眼的位置。
    • 好吧,这是有道理的。我的操作是假设 Vue 在 DOM 实际准备好时正在监听来自浏览器的事件回调。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2014-09-03
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多