2016-07-24 3 views
0

Ich habe eine einfache App, die Bootstrap, vue.js und chart.js verwendet. Die HTML-Vorlage ist ziemlich einfach. Bei der Suche nach meinem Fehler ist mir aufgefallen, dass dieses Problem häufig beim Rendern eines Diagramms in einer Registerkarte oder in einem Modal auftritt, aber ich habe mein Diagramm nicht in einem Modal oder Tab.Chart.js rendern nicht mit vue.js, bis das Fenster die Größe ändert

Sobald ich die Größe meines Browserfensters ändere, wird das Diagramm korrekt gerendert und skaliert, damit es in das div und alles passt.

Aus welchen Gründen auch immer, wenn die Seite geladen wird, macht die Leinwand HTML-Tag wie folgt aus:

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

Aber wenn ich die Fenster, alles ändert sich die Größe und ich sehe richtig das Diagramm.

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

Warum ist es nicht die Höhe & Breite korrekte Laden der Seite bekommen?

HTML-Vorlage

<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> 

Antwort

3

Zugriff auf DOM in ready() ist heikel, weil Vue DOM asynchron aktualisiert, so dass Änderungen angewendet wurden möglicherweise noch nicht vollständig, und/oder der Browser hat noch kein neues Layout erstellt.

Verwendung $nextTick() aufzuschieben, bis die Aktualisierung abgeschlossen ist:

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

Diese in der Regel funktioniert der Trick in diesen Situationen zumindest auf der Vue-Seite der Dinge. Ich kann nicht viel über die chart.js-Konfiguration sagen.

+0

Wow, das hat funktioniert. Vielen Dank! Frage aber. Ist das ein Fehler in Vue? Ich würde denken, dass die Methode 'ready()' genauso funktionieren würde wie in jQuery. Oder benutzte ich es falsch und ich sollte immer '$ nextTick' verwenden? – Nathan

+1

Nein, es ist kein Fehler in Vue. Wie gesagt, Vue [aktualisiert das DOM asynchron] (http://vuejs.org/guide/reactivity.html#Async-Update-Queue) aus Leistungsgründen, was bedeutet, dass wenn Vue sagt "setze dieses Element in das DOM" , und feuert den ready() - Haken danach, "dieses Element" ist möglicherweise noch nicht im DOM. Da dies eine der häufigsten Fallstricke ist, denen die Leute zu begegnen scheinen, werde ich vorschlagen, sie den Dokumenten besser hinzuzufügen. –

+0

OK, das macht Sinn. Ich ging davon aus, dass Vue auf einen Ereignis-Callback vom Browser wartete, als das DOM tatsächlich fertig war. – Nathan

Verwandte Themen