1

首先,我想说这个问题并不是一成不变的,因为我非常愿意尝试其他建议,因为我可能完全错过了一个合适的方法。

我在 JSX 中使用 Vue-ChartJs,但希望在应用程序开始时不必扩展我需要的每个图表组件,例如:

    // Line bar component.
Vue.component('line-chart', {
    extends: VueChartJs.Line,

    props: ['data', 'options'],

    mounted() {
        this.renderChart(this.data, this.options)
    }
});

相反,我想动态扩展组件,也许,一个 prop 将确定要扩展的内容:

const getChart = (type) => {
    if (type === 'bar') {
        return VueChartJs.Bar;
    };
};

Vue.component('chart', {
    props: ['data', 'options', 'type'],
    extends: () => {
        getChart(this.type)
    },
    mounted() {
        this.renderChart(this.data, this.options)
    }
})

这个方法目前不起作用,因为在 extends: 它返回一个错误 t is undefined which "this" 没有被设置。

对可能的解决方案有什么建议吗?提前致谢。

4

3 回答 3

3

在您的示例中,该type属性有效地决定了使用哪个组件。内置属性is更适合这项工作。请注意,这里我仍然注册所有组件,但是使用 util 函数使代码非常简短和容易。

<div id="app">
    <div>
        <!-- think of :is like the :type property in your example, it serves the same purpose -- deciding which component to use -->
        <component :is="chartTypeLine" :data="chartData" :options="chartOptions"></component>
        <component :is="chartTypeBar" :data="chartData" :options="chartOptions"></component>
    </div>

</div>

<script src="https://vuejs.org/js/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.min.js"></script>
<script>

    const getChart = (type) => {
        switch (type) {
            case 'line-chart':
                return VueChartJs.Line;
            case 'bar-chart':
                return VueChartJs.Bar;
            default:
                throw new Error("wrong chart type");
        }
    };

    const chartTypes = ['line-chart', 'bar-chart'];

    //this makes registering all those components easier.
    chartTypes.forEach(type => {
        Vue.component(type, {
            extends: getChart(type),
            props: ['data', 'options'],
            mounted () {
                this.renderChart(this.data, this.options)
            }
        })
    });

    new Vue({
        el: '#app',
        data: {
            chartData: {
                labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
                datasets: [
                    {
                        backgroundColor: '#f87979',
                        data: [40, 39, 10, 40, 39, 80, 40]
                    }
                ]
            },
            chartOptions: {responsive: true, maintainAspectRatio: false},
            chartTypeLine: 'line-chart',
            chartTypeBar: 'bar-chart'
        }
    })
</script>

https://codepen.io/anon/pen/MBxRpP

于 2018-08-13T17:09:47.857 回答
1

除了之前的答案,我今天早上还发现了另一种方法。它在 JSX 文件首次运行时使用相同的 foreach 循环通过一个对象实例化每个图表类型,这会将它们全部注册到准备使用的范围内。

const chartNames = [
    {
        name: 'line-chart',
        type: VueChartJs.Line
    }, {
        name: 'bar-chart',
        type: VueChartJs.Bar
    },
    {
        name: 'horizontal-bar-chart',
        type: VueChartJs.HorizontalBar
    },
    {
        name: 'doughnut-chart',
        type: VueChartJs.Doughnut
    },
    {
        name: 'pie-chart',
        type: VueChartJs.Pie
    },
    {
        name: 'radar-chart',
        type: VueChartJs.Radar
    },
    {
        name: 'polar-area-chart',
        type: VueChartJs.PolarArea
    },
    {
        name: 'bubble-chart',
        type: VueChartJs.Bubble
    },
    {
        name: 'scatter-chart',
        type: VueChartJs.Scatter
    }];
const registerCharts = (chartNames) => {
    chartNames.forEach((chartName) => {
        Vue.component(chartName.name, {
            extends: chartName.type,
            mixins: [VueChartJs.mixins.reactiveProp],
            props: {
                options: Object
            },
            methods: {
                // Used in the alternate render version, this updates the chart in question.
                update() {
                    this.$data._chart.update()
                }
            },
            mounted() {
                this.renderChart(this.chartData, this.options)
            }
        });
    })
};
registerCharts(chartNames);
于 2018-08-14T07:48:00.377 回答
0

我喜欢这个

图表.js

import VueChartJs from 'vue-chartjs'
import Vue from 'vue'

const getChart = (type) => {
  switch (type) {
    case 'LineChart':
      return VueChartJs.Line
    case 'BarChart':
      return VueChartJs.Bar
    case 'PieChart':
      return VueChartJs.Pie
    default:
      throw new Error('wrong chart type')
  }
}

// generate component via fun
// it mean that you will generate as many components as you need

export default (type) => {
  return Vue.component(type, {
    extends: getChart(type),
    name: type,
    props: ['data', 'options'],
    mounted () {
      this.renderChart(this.data, this.options)
    }
  })
}

索引.vue

<template> 
..
        <PieChart
          :data="testData"
          :options="options"
        />
..
</template>

<script>
import Chart from '~/components/UI/Chart/index'
..
export default {
  components: {
    PieChart: Chart('PieChart')
  }

}
</script>
于 2021-03-26T10:38:23.907 回答