Chart.js图表无法更新API数据 求排查导入及代码问题
问题
我在网站中使用Chart.js绘制图表,但图表无法更新来自API的信息。猜测可能是Chart.js导入方式有误——我在index.html和脚本自身的JS文件中使用了相同的脚本导入配置,不清楚问题出在哪里。核心代码如下:
function removeElementsByClass(className) { const elements = document.getElementsByClassName(className); while(elements.length > 0) { elements[0].parentNode.removeChild(elements[0]); } } function draw_graph(graph_data, header) { var accepted = [], rejected = [], timestamps = []; if(typeof header === 'undefined') header = ''; for(var timestamp in graph_data) { accepted.push(Math.round(graph_data[timestamp]['a'])); // accepted_hashes timestamps.push(timestamp); } Chart.defaults.global.defaultFontFamily = 'Verdana'; Chart.defaults.global.defaultFontStyle = 'normal'; Chart.defaults.global.defaultFontColor = '#0B6FAB'; Chart.defaults.global.defaultFontSize = 11; Chart.defaults.global.legend = false; removeElementsByClass('chartjs-hidden-iframe'); new Chart(document.getElementById("global-speed-chart"), { type:'line', data: { labels: timestamps, datasets: [{ data: accepted, borderColor: '#0B6FAB', backgroundColor: '#CBFFFF', borderWidth: 2, fill: false, pointRadius: 0 } ] }, options: { title: { display: true, text: header, fontSize: 16 }, legend: { labels: { fontColor: '#C0C0C0' } }, scales: { yAxes: [{ position: 'right', gridLines: { drawBorder: false }, ticks: { beginAtZero: true, maxTicksLimit: 3, fontStyle: 'bold', fontColor: '#C0C0C0', fontSize: 9, userCallback: function(label, index, labels) { if(label !== 0) { return label; } } } }], xAxes: [{ gridLines: { drawBorder: false, display:false }, ticks: { beginAtZero: true, autoSkip: true, maxTicksLimit: 6, fontColor: '#C0C0C0', fontSize: 9, maxRotation: 0, minRotation: 0 } }] } }}); };
解决方案
1. 修复重复导入问题
删除index.html或JS文件中任意一处的Chart.js导入,只保留单处全局导入即可。重复导入会导致Chart全局对象被多次覆盖,引发实例管理混乱。
2. 修正图表更新逻辑(核心问题)
当前代码每次调用draw_graph都会创建新的Chart实例,旧实例未销毁,导致新图表叠加在旧图表上,视觉上看起来没有更新。修改方式:
- 全局存储图表实例,每次绘制前销毁旧实例
- 移除粗暴的DOM操作
removeElementsByClass('chartjs-hidden-iframe'),Chart.js会自动管理内部元素
修改后的核心代码:
// 全局存储图表实例,用于后续销毁 let globalChart = null; function removeElementsByClass(className) { const elements = document.getElementsByClassName(className); while(elements.length > 0) { elements[0].parentNode.removeChild(elements[0]); } } function draw_graph(graph_data, header) { var accepted = [], rejected = [], timestamps = []; if(typeof header === 'undefined') header = ''; for(var timestamp in graph_data) { accepted.push(Math.round(graph_data[timestamp]['a'])); timestamps.push(timestamp); } // 全局配置移到页面初始化时执行一次即可,无需重复设置 Chart.defaults.global.defaultFontFamily = 'Verdana'; Chart.defaults.global.defaultFontStyle = 'normal'; Chart.defaults.global.defaultFontColor = '#0B6FAB'; Chart.defaults.global.defaultFontSize = 11; Chart.defaults.global.legend = false; // 销毁旧图表实例 if (globalChart) { globalChart.destroy(); } // 创建新图表并保存实例 globalChart = new Chart(document.getElementById("global-speed-chart"), { type:'line', data: { labels: timestamps, datasets: [{ data: accepted, borderColor: '#0B6FAB', backgroundColor: '#CBFFFF', borderWidth: 2, fill: false, pointRadius: 0 } ] }, options: { title: { display: true, text: header, fontSize: 16 }, legend: { labels: { fontColor: '#C0C0C0' } }, scales: { yAxes: [{ position: 'right', gridLines: { drawBorder: false }, ticks: { beginAtZero: true, maxTicksLimit: 3, fontStyle: 'bold', fontColor: '#C0C0C0', fontSize: 9, userCallback: function(label, index, labels) { if(label !== 0) { return label; } } } }], xAxes: [{ gridLines: { drawBorder: false, display:false }, ticks: { beginAtZero: true, autoSkip: true, maxTicksLimit: 6, fontColor: '#C0C0C0', fontSize: 9, maxRotation: 0, minRotation: 0 } }] } }}); };
3. 额外注意事项
- 确保
draw_graph在API数据返回后调用,比如放在fetch或axios的回调函数中 - 全局配置
Chart.defaults.global建议移到页面初始化时执行一次,避免重复设置影响性能
内容的提问来源于stack exchange,提问作者jade1411
相关产品推荐
相关产品推荐

