menu
書いてる野郎
orebike@gmail.com
やってみる。
$ npm install --save vue-chartjs chart.js
このラッパーはスーパークラスとして提供されているようなのでまずはそれを継承して独自のコンポーネントを作る。
MyChart.js を作ってここに棒グラフを作ろうと思う。
こうなる。
import Vue from 'vue'; import VueChartjs from 'vue-chartjs'; Vue.component("my-chart", { extends: VueChartjs.Bar, mixins: [VueChartjs.mixins.reactiveProp], mounted: function(){ this.renderChart(this.chartData); } });
これは棒グラフを継承している
extends: VueChartjs.Bar,
これは実際にはよくわかってないのだが、こいつを書いておくと、自動的に chartData という props が作られる。
mixins: [VueChartjs.mixins.reactiveProp]
これは普通に Vue オブジェクトの props に該当するのだが、 名前が固定になっていて、しかも使い道も限定されていて、中身が問答無用で rendarChart メソッドに送り込まれるようになっている。
mounted はライフサイクルフックで、マウント時に実行される。 とりあえず描画しておかないとだめなようなので入れている。 内部で使っている this.chartData は↑で暗黙で作られているのを利用している。
指定された名前 chart-data でバインドする。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Hello</title> <!-- 今回ビルドしたやつ --> <script src="dist/bundle.js"></script> </head> <body> <div id="app"> <!-- これがチャート --> <my-chart v-bind:chart-data="chartDataAll"></my-chart> </div> <script> var vm = new Vue({ el: "#app", computed: { chartDataAll: function(){ return { labels: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], datasets: [ { label: 'my chart', backgroundColor: '#f87979', data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11] } ] }; } } }); </script> </body> </html>
ここで問題なのは、chart-data にバインディングされた値が、問答無用で全部 renderChart に送り込まれてしまうということである。
つまり、チャートの詳しい触らなくてもいいパラメータすら使う側が全部知っておかないといけないという状態になる。
親が配下のデータを全部知らないといけないなんか現実的ではないので 別のやり方を試す。
先程の VueChartjs.mixins.reactiveProp の代わりに VueChartjs.mixins.reactiveData を使うというもの。
これは、reactiveProp が chartData という props を更新するとチャートが自動再描画されたのと似ていて、 this.chartData という data が更新されると画面が再描画される。というもの。
これなら更新時に介入できそうである。
props を使わないので自力で作る。 そして props の更新と再描画トリガーが離れてしまうのでここも自力で作る。 そのかわりそこに介入できる。
こうなる。
import Vue from 'vue'; import VueChartjs from 'vue-chartjs'; Vue.component("my-chart", { extends: VueChartjs.Bar, mixins: [VueChartjs.mixins.reactiveData], props: ['mydata'], mounted: function(){ this.renderChart(this.chartData); }, watch: { mydata: function() { this.chartData = { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], datasets: [ { label: 'my chart', backgroundColor: '#f87979', data: this.mydata } ] }; } } });
watch で props の更新を監視して、親からバインドされたデータを加工して this.chartData に渡している。
あとは、親はバインドしてやればいい。
<my-chart v-bind:mydata="chartDataAll"></my-chart>
先程と違い、本当にデータの部分だけをバインドしてやればいいので親は子の細かいパラメータを知る必要が無い。