You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3组合式API+vue-chartjs:如何用API数据更新chartData

解决Vue3 + vue-chartjs动态更新饼图数据的问题

问题分析

当前核心问题:

  • 子组件chart.vue中chartData是硬编码的固定值,未关联父组件传递的charts props数据
  • 子组件props里charts类型定义错误(父组件传数组,却定义为Object)
  • 循环渲染的所有饼图共用同一个chartData,未对应到每个独立的chart项

解决方案步骤

1. 修正父组件的小问题

父组件中console.log(charts.notApplicable)需改为console.log(charts.value),因为charts是ref对象,必须通过.value访问内部值:

// viewChart.vue 中getCharts函数修改
const getCharts = async () => {
    try {
        const response = await axios.get('http://localhost:3000/api/charts/',{
            headers: {
                "Content-Type": "application/json",
            }
        })
        charts.value = response.data
        console.log(charts.value) // 修正此处
    } catch (error) {
        console.error(error) // 添加错误日志方便排查
    }
}

2. 修正子组件的props类型

子组件中charts的props类型改为Array(匹配父组件传递的数组类型):

// chart.vue 中defineProps部分修改
const props = defineProps({
    // 其他props保持不变
    charts: {
        type: Array, // 从Object改为Array
        default: () => []
    }
})

3. 动态绑定每个饼图的数据源

移除子组件中硬编码的chartData,改为为每个循环的chart项动态生成对应数据:

在子组件的<script setup>中添加生成饼图数据的方法:

const getChartData = (chartItem) => {
    // 假设API返回的每个chartItem包含以下字段,根据实际接口结构调整
    return {
        labels: ['Implemented', 'Partially Implemented', 'Not Implemented', 'Not Applicable'],
        datasets: [{
            backgroundColor: ['Green', 'Orange', 'Red', 'Grey'],
            data: [
                chartItem.implemented,
                chartItem.partiallyImplemented,
                chartItem.notImplemented,
                chartItem.notApplicable
            ]
        }]
    }
}

修改模板,让每个Pie组件绑定对应chart项的动态数据,并设置唯一chart-id:

<template>
    <div style="color:black;">
        <h2 class="text-black">Title</h2>
        <div v-for="chartItem in charts" :key="chartItem.id">
            <Pie 
                :chart-options="chartOptions"
                :chart-data="getChartData(chartItem)" <!-- 绑定动态数据 -->
                :chart-id="`pie-chart-${chartItem.id}`" <!-- 唯一ID避免冲突 -->
                :dataset-id-key="datasetIdKey"
                :plugins="plugins"
                :css-classes="cssClasses"
                :styles="styles"
                :width="width"
                :height="height"
            />
        </div>
    </div>
</template>

4. 响应式更新说明

Vue的响应式系统会自动追踪props.charts的变化,当父组件API数据更新后,子组件循环会重新渲染,getChartData方法生成新的饼图数据,vue-chartjs会自动更新图表,无需额外使用watch或emit。

完整子组件代码(修改后)

<template>
    <div style="color:black;">
        <h2 class="text-black">Title</h2>
        <div v-for="chartItem in charts" :key="chartItem.id">
            <Pie 
                :chart-options="chartOptions"
                :chart-data="getChartData(chartItem)"
                :chart-id="`pie-chart-${chartItem.id}`"
                :dataset-id-key="datasetIdKey"
                :plugins="plugins"
                :css-classes="cssClasses"
                :styles="styles"
                :width="width"
                :height="height"
            />
        </div>
    </div>
</template>

<script setup>
import { reactive } from 'vue'
import { Pie } from  'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, CategoryScale } from 'chart.js'

ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale)

const props = defineProps({
    chartId:{
        type: String,
        default: 'pie-chart' 
    },
    datasetIdKey:{
        type: String,
        default: 'label'
    },
    width: {
        type: Number,
        default: 300
    },
    height: {
        type: Number,
        default: 500
    },
    cssClasses: {
        default: '',
        type: String
    },
    styles: {
        type: Object,
        default: () => {}
    },
    plugins: {
        type: Object,
        default: () => {}
    },
    charts: {
        type: Array,
        default: () => []
    }
})

const getChartData = (chartItem) => {
    return {
        labels: ['Implemented', 'Partially Implemented', 'Not Implemented', 'Not Applicable'],
        datasets: [{
            backgroundColor: ['Green', 'Orange', 'Red', 'Grey'],
            data: [
                chartItem.implemented,
                chartItem.partiallyImplemented,
                chartItem.notImplemented,
                chartItem.notApplicable
            ]
        }]
    }
}

const chartOptions = reactive({
    responsive: true,
    maintainAspectRatio: false,
    plugins:{
        legend:{
            display:true,
            position:'bottom',
        }
    }
})
</script>

内容的提问来源于stack exchange,提问作者San

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:55:19