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

Vue3(Options API)中Vue-ChartJS柱状图无法更新的问题

Vue3 Options API中vue-chartjs柱状图数据更新不显示的解决方法

问题根源分析

  1. 响应式检测失效:直接修改this.data.datasets的元素(如push、filter赋值),Vue对对象/数组的深层变更检测存在限制,导致组件无法感知数据变化。
  2. ref调用错误:this.$refs.chart获取的是Vue组件实例,而非ChartJS的图表实例,直接调用update()自然会报错。

具体修复步骤

1. 确保数据变更触发Vue响应式更新

修改setData方法,通过创建新对象/数组的方式更新数据,让Vue能准确检测到变化:

setData(value) {
  let newDatasets = [...this.data.datasets]; // 复制原数组,避免直接修改原引用
  if (value.length > 0 && value.length < 5) {
    value.forEach(val => {
      if (val.selected) {
        const exist = newDatasets.find(el => el.label === val.label);
        if (!exist) {
          const obj = {
            label: val.label,
            data: graphData.data[this.text][val.label],
            backgroundColor: this.generateColor()
          };
          newDatasets.push(obj);
        }
      } else {
        newDatasets = newDatasets.filter(dataset => dataset.label !== val.label);
      }
    });
  } else {
    newDatasets = [];
  }
  // 重新赋值data对象,触发响应式更新
  this.data = { ...this.data, datasets: newDatasets };
  
  // 可选:手动触发图表更新(确保Chart实例存在)
  if (this.$refs.chart?.chart) {
    this.$refs.chart.chart.update();
  }
}

2. 正确调用ChartJS的update方法

如果需要手动触发图表更新,必须通过Vue组件实例的chart属性获取ChartJS实例:

// 先判断组件和chart实例是否存在,避免报错
if (this.$refs.chart && this.$refs.chart.chart) {
  this.$refs.chart.chart.update();
}

3. 优化key强制刷新(可选)

若上述方法仍不生效,可利用:key属性强制组件重新渲染。在setData末尾更新value的值:

this.value += 1;

4. 移除冗余计算属性

newData计算属性仅直接返回this.data,无实际作用,直接在模板中使用:data="data"即可:

<Bar ref="chart" :key="value" :data="data" :options="options" />

完整修复后的代码示例

Template部分

<template>
  <div>
    <div>
      <Bar ref="chart" :key="value" :data="data" :options="options" />
    </div>
  </div>
</template>

Script部分

<script>
import { Bar } from 'vue-chartjs'
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  Title,
  Tooltip,
  BarElement,
  Legend
} from 'chart.js'
ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  BarElement,
  Title,
  Tooltip,
  Legend
)
import graphData from '../../data/GraphData.json'
export default {
  components: {
    Bar
  },
  data() {
    return {
      value: 1,
      text: 'Multikills',
      data: {
        labels: [
          'Romex Fortrex',
          'OBG BotGapped',
          'Hou Max',
          'OBG Logic',
          'OBG Thanagor'
        ],
        datasets: [
          {
            label: 'Two',
            data: [15, 20, 5, 8, 15],
            backgroundColor: '#ADD8E6'
          }
        ]
      },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        elements: {
          line: {
            borderColor: 'white'
          }
        },
        scales: {
          y: {
            ticks: {
              color: 'white',
              font: {
                family: 'MarkPro',
                weight: 'bold'
              }
            },
            title: {
              display: true,
              color: 'white',
              text: 'Winrate',
              font: {
                family: 'MarkPro',
                size: 14,
                weight: 'bold'
              }
            }
          },
          x: {
            ticks: {
              color: 'white',
              font: {
                family: 'MarkPro',
                weight: 'bold'
              }
            },
            title: {
              display: true,
              color: 'white',
              text: 'Number of games',
              font: {
                family: 'MarkPro',
                size: 14,
                weight: 'bold'
              }
            }
          }
        },
        plugins: {
          legend: {
            labels: {
              color: 'white',
              font: {
                family: 'MarkPro',
                weight: 'bold'
              }
            }
          }
        }
      }
    }
  },
  methods: {
    setData(value) {
      let newDatasets = [...this.data.datasets];
      if (value.length > 0 && value.length < 5) {
        value.forEach(val => {
          if (val.selected) {
            const exist = newDatasets.find(el => el.label === val.label);
            if (!exist) {
              const obj = {
                label: val.label,
                data: graphData.data[this.text][val.label],
                backgroundColor: this.generateColor()
              };
              newDatasets.push(obj);
            }
          } else {
            newDatasets = newDatasets.filter(dataset => dataset.label !== val.label);
          }
        });
      } else {
        newDatasets = [];
      }
      this.data = { ...this.data, datasets: newDatasets };
      
      if (this.$refs.chart?.chart) {
        this.$refs.chart.chart.update();
      }
      
      // 若仍不更新,取消注释以下代码强制刷新组件
      // this.value += 1;
    },
    generateColor() {
      const red = Math.floor(Math.random() * 101) + 100;
      const green = Math.floor(Math.random() * 101) + 100;
      const blue = Math.floor(Math.random() * 101) + 100;
      return `#${red.toString(16)}${green.toString(16)}${blue.toString(16)}`;
    }
  }
}
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:13:18