Chart.js图表刷新后不显示,打开F12控制台后恢复显示求助
问题原因与解决方案
核心原因
你直接修改了stocksData内部的labels和datasets数组元素,Angular的变更检测机制无法捕捉到这种对象内部属性的修改,导致ng2-charts没有触发图表重绘。而打开控制台触发窗口resize时,ng2-charts会监听resize事件并主动调用图表更新方法,此时数据已经加载完成,所以图表能正常显示。
解决方案
方案1:重新赋值stocksData(推荐)
通过重新创建stocksData对象,触发引用变更,让Angular检测到数据变化并更新图表:
import { Component } from '@angular/core'; import { ChartData } from 'chart.js'; import { IInventory } from 'src/app/models/inventory'; import { IStorage } from 'src/app/models/storage'; import { InventoryService } from 'src/app/services/inventory.service'; import { StorageService } from 'src/app/services/storage.service'; @Component({ selector: 'app-stocks-chart', templateUrl: './stocks-chart.component.html', styleUrls: ['./stocks-chart.component.scss'] }) export class StocksChartComponent { stocks: IInventory[] storages: IStorage[] selectedStorage: string = '' stocksData: ChartData<'doughnut'> = { labels: [], datasets: [ { data: [] } ] } stocksLabels: string[] constructor(private inventory: InventoryService, private storages: StorageService) { inventory.getInventory().subscribe((res: IInventory[]) => { this.stocks = res; // 用Map整理数据,避免重复遍历查找 const productStockMap = new Map<string, number>(); res.forEach(item => { const currentStock = productStockMap.get(item.productName) || 0; productStockMap.set(item.productName, currentStock + item.stock); }); // 重新赋值整个stocksData对象 this.stocksData = { labels: Array.from(productStockMap.keys()), datasets: [{ data: Array.from(productStockMap.values()) }] }; }) } }
方案2:手动触发变更检测
注入ChangeDetectorRef,在修改数据后手动通知Angular检测变化:
import { Component, ChangeDetectorRef } from '@angular/core'; import { ChartData } from 'chart.js'; import { IInventory } from 'src/app/models/inventory'; import { IStorage } from 'src/app/models/storage'; import { InventoryService } from 'src/app/services/inventory.service'; import { StorageService } from 'src/app/services/storage.service'; @Component({ selector: 'app-stocks-chart', templateUrl: './stocks-chart.component.html', styleUrls: ['./stocks-chart.component.scss'] }) export class StocksChartComponent { stocks: IInventory[] storages: IStorage[] selectedStorage: string = '' stocksData: ChartData<'doughnut'> = { labels: [], datasets: [ { data: [] } ] } stocksLabels: string[] constructor( private inventory: InventoryService, private storages: StorageService, private cdr: ChangeDetectorRef ) { inventory.getInventory().subscribe((res: IInventory[]) => { this.stocks = res res.map((item: IInventory) => { if (this.stocksData.labels?.includes(item.productName)) { this.stocksData.datasets[0].data[this.stocksData.labels.indexOf(item.productName)] += item.stock } else { this.stocksData.labels?.push(item.productName) this.stocksData.datasets[0].data.push(item.stock) } }); // 手动触发变更检测 this.cdr.detectChanges(); }) } }
方案3:手动调用图表更新方法
获取图表指令引用,在数据加载完成后主动调用更新:
- 修改HTML模板,添加模板引用:
<canvas #chartRef baseChart type="doughnut" [data]="stocksData" ></canvas>
- 修改Component代码:
import { Component, ViewChild } from '@angular/core'; import { ChartData } from 'chart.js'; import { BaseChartDirective } from 'ng2-charts'; import { IInventory } from 'src/app/models/inventory'; import { IStorage } from 'src/app/models/storage'; import { InventoryService } from 'src/app/services/inventory.service'; import { StorageService } from 'src/app/services/storage.service'; @Component({ selector: 'app-stocks-chart', templateUrl: './stocks-chart.component.html', styleUrls: ['./stocks-chart.component.scss'] }) export class StocksChartComponent { stocks: IInventory[] storages: IStorage[] selectedStorage: string = '' stocksData: ChartData<'doughnut'> = { labels: [], datasets: [ { data: [] } ] } stocksLabels: string[] @ViewChild('chartRef') chartRef!: BaseChartDirective; constructor(private inventory: InventoryService, private storages: StorageService) { inventory.getInventory().subscribe((res: IInventory[]) => { this.stocks = res res.map((item: IInventory) => { if (this.stocksData.labels?.includes(item.productName)) { this.stocksData.datasets[0].data[this.stocksData.labels.indexOf(item.productName)] += item.stock } else { this.stocksData.labels?.push(item.productName) this.stocksData.datasets[0].data.push(item.stock) } }); // 手动更新图表 this.chartRef.update(); }) } }
内容的提问来源于stack exchange,提问作者DeadWinner
相关产品推荐
相关产品推荐

