2

我想通过反应性将数据从父级传递给 GrandChild(即图表),所以我正在使用道具。

这是家长

下面的“kalkulator-data”组件已工作,它用于将数据添加到Parent

<template>
    <div class="container">
        <div class="row">

                <kalkulator-data 
                    :saldoAwal="saldoAwal" 
                    :saldoTerpakai="saldoTerpakai" 
                    :saldoAkhir="saldoAkhir"
                    :dataKategori="dataKategori"
                    :dataPengeluaran="dataPengeluaran"

                    @inputSaldo="saldoAwal = $event"
                    @inputPengeluaran="dataPengeluaran.push($event)">

                </kalkulator-data>

                <kalkulator-chart
                    :chartData="chartData"
                    :chartOptions="chartOptions">    

                </kalkulator-chart>

        </div>
    </div>
</template>

<script>
    import Chart from './Bagian/Chart.vue';
    import Data from './Bagian/Data.vue';

    export default {
        data(){
            return {
                saldoAwal : 0,
                dataPengeluaran : [{ kategori : 'Abi', nominal : 12}, { kategori : 'Ilham', nominal : 13}],
                dataKategori : [
                    'Makan dan Minum',
                    'Berbelanja',
                    'Perlengkapan Rumah',
                    'Transportasi',
                    'Kendaraan',
                    'Gaya Hidup dan Hiburan',
                    'Komunikasi',
                    'Pengeluaran dan Finansial',
                    'Investasi',
                ],
                chartOptions : {responsive: true, maintainAspectRatio: false}
            }
        },
        computed : {
            saldoTerpakai(){
                var saldoPakai = 0;
                for(var data of this.dataPengeluaran){
                    saldoPakai += parseInt(data.nominal);
                }
                return saldoPakai;
            },
            saldoAkhir(){
                return this.saldoAwal - this.saldoTerpakai;
            },
            getRandomColor(){
                var letters = '0123456789ABCDEF';
                var color = '#';
                for (var i = 0; i < 6; i++) {
                    color += letters[Math.floor(Math.random() * 16)];
                }
                return color;
            },
            chartLabels(){
                var chartLabels = [];
                for (var data of this.dataPengeluaran ){
                    chartLabels.push(data.kategori);
                    // backgroundColor.push(this.getRandomColor);
                };
                return chartLabels;
            },
            chartId(){
                var chartData = [];
                for (var data of this.dataPengeluaran ){
                    chartData.push(parseInt(data.nominal));
                    // backgroundColor.push(this.getRandomColor);
                };
                return chartData;
            },
            chartData(){
                return {
                    labels: this.chartLabels,
                    datasets: [
                      {
                        label: 'Data One',
                        backgroundColor: '#f87979',
                        data: this.chartId
                      }
                    ]
                }
            }
        },
        methods : {

        },
        components : {
            'kalkulator-data' : Data,
            'kalkulator-chart' : Chart
        },
    }
</script>

这是孩子

<template>
    <div class="col-sm-6">
        <div class="row">
            <h1 class="text-center">Struktur Pengeluaran</h1>

            <chart-comp 
                :chartData="chartData"
                :chartOptions="chartOptions">               
            </chart-comp>

        </div>
    </div>
</template>

<script>
    import chartComp from './Chart-Data.js'

    export default{
        props : ['chartData', 'chartOptions'],
        components : {
            'chart-comp' : chartComp
        }
    }
</script>

这就是图表的GrandChild

import {Bar} from 'vue-chartjs'

export default Bar.extend({
    props : ['chartData', 'chartOptions'],
    computed : {
        renderChart(){
            this.renderChart(this.chartData, this.chartOptions);
        }
    },
    mounted () {
        this.renderChart;
    }
})

当我添加数据时,我使用计算来保持反应性,但它​​在控制台中说:

app.js:5366 [Vue warn]: Error in mounted hook: "RangeError: Maximum call stack size exceeded"

found in

---> <ChartComp>
       <KalkulatorChart> at C:\xampp\htdocs\SemuaOkee-Laravel\resources\assets\js\components\Bagian\Chart.vue
         <Kalkulator> at C:\xampp\htdocs\SemuaOkee-Laravel\resources\assets\js\components\Kalkulator.vue
           <Root>
warn @ app.js:5366
handleError @ app.js:5451
callHook @ app.js:7490
insert @ app.js:8315
invokeInsertHook @ app.js:10143
patch @ app.js:10308
Vue._update @ app.js:7248
updateComponent @ app.js:7371
get @ app.js:7710
Watcher @ app.js:7693
mountComponent @ app.js:7375
Vue$3.$mount @ app.js:12503
Vue$3.$mount @ app.js:14602
Vue._init @ app.js:8942
Vue$3 @ app.js:9027
(anonymous) @ app.js:29926
__webpack_require__ @ app.js:20
(anonymous) @ app.js:29888
__webpack_require__ @ app.js:20
(anonymous) @ app.js:63
(anonymous) @ app.js:66
app.js:5455 RangeError: Maximum call stack size exceeded
    at Watcher.evaluate (app.js:7809)
    at VueComponent.computedGetter [as renderChart] (app.js:8064)
    at VueComponent.renderChart (app.js:61047)
    at Watcher.get (app.js:7710)
    at Watcher.evaluate (app.js:7810)
    at VueComponent.computedGetter [as renderChart] (app.js:8064)
    at VueComponent.renderChart (app.js:61047)
    at Watcher.get (app.js:7710)
    at Watcher.evaluate (app.js:7810)
    at VueComponent.computedGetter [as renderChart] (app.js:8064)

当我仍然没有添加数据时,它工作得很好(这就是为什么我在Parent中硬编码两个对象以在开始时测试我的图表),但是当我添加数据时它出现了错误。

换句话说,它适用于静态数据,但不适用于动态数据。

4

2 回答 2

4

在您的孙子组件中,您定义了一个renderChart返回的计算属性this.renderChart。这就是导致最大调用堆栈大小错误的原因。

您应该只调用钩子renderChart中的方法:mounted

import { Bar } from 'vue-chartjs'

export default Bar.extend({
    props: ['chartData', 'chartOptions'],
    mounted() {
        this.renderChart(this.chartData, this.chartOptions);
    }
})

如果您需要图表数据是响应式的,vue-chartjs 提供了一种公认的愚蠢方式来指定使用 mixin:

import { Bar, mixins } from 'vue-chartjs'

export default Bar.extend({
    props: ['chartData', 'chartOptions'],
    mixins: [mixins.reactiveProp],
    mounted() {
        this.renderChart(this.chartData, this.chartOptions);
    }
})

这是关于使用响应式数据的 vue-chartjs 文档。

于 2017-07-14T12:59:19.447 回答
0

我在渲染组件时在 vue.js 中遇到了同样的错误,你必须在重新填充值之前销毁图表,你可以像下面那样做:

<script>
import Chart from 'chart.js';
export default {
  name: 'card',
  props: {
  chartData: {
    type: Object,
    required: true,
  },
},
mounted() {
    this.createChart('planet-chart', this.chartData);
},
data() {
    return {
        myChart: null
    }
},
methods:{
    createChart(chartId, chartData) {
        const ctx = document.getElementById(chartId);
        this.myChart = new Chart(ctx, {
            type: chartData.type,
            data: chartData.data,
            options: chartData.options,
        });
    }
},
beforeDestroy() {
   if(this.myChart) {
        this.myChart.destroy();
    } 
 }
};
</script>
于 2019-11-14T03:00:07.503 回答