JavaScript中GKChart类多实例画布图表Resize响应问题求助
解决多个GKChart实例resize时仅最后一个重绘的问题
嘿,我来帮你分析下问题根源,然后给出具体的修复方案。
问题所在
你的代码里有两个关键问题导致了只有最后一个图表实例会在resize时重绘:
- 重复绑定resize事件:每次实例化
GKChart时,resize方法都会给window添加一层resize事件监听,而且还嵌套了另一层监听!这会导致事件被多次绑定,后续的实例会覆盖前面的逻辑。 - 全局变量覆盖:你用了全局的
window.resizeEvt来做防抖,每次新实例创建时都会覆盖这个变量,最后只有最后一个实例的重绘函数会被执行。
修复方案
我们可以通过全局统一管理所有实例的重绘函数,只绑定一次resize事件来解决这个问题。修改后的GKChart类如下:
class GKChart { // 静态数组:保存所有图表实例的重绘函数 static resizeHandlers = []; // 静态标记:确保全局只绑定一次resize事件 static isResizeBound = false; constructor(data) { try { console.info("Enter: Chart Designing initialize function"); this.chartID = data.id; this.chartData = data.data; this.chartCall = new chartCalling(); this.load = this.initialize(this.chartData.config.chartType, this.chartData, this.chartID, this.chartCall); this.load(); // 将当前实例的重绘函数加入全局数组 GKChart.resizeHandlers.push(this.load); // 全局仅绑定一次resize事件 this.bindGlobalResize(); console.info("Exit: Chart Designing initialize function"); } catch (err) { console.log("Error Found in GKChart Constructor", err); } } initialize(chartTypeLoad, chartDataLoad, chartIDLoad, chartCallLoad) { try { console.log("Start : initialize"); const chartType = chartTypeLoad; const chartData = chartDataLoad; const chartID = chartIDLoad; const chartCall = chartCallLoad; // 重绘函数,通过闭包捕获当前实例的配置 const loadIt = () => { console.warn("Resize Load : " + chartID); css(document.querySelector("#" + chartID), { 'display': 'block' }); switch (chartType) { case "line": chartCall.lineChart(chartData, chartID); break; case 'bar': chartCall.barChart(chartData, chartID); break; default: console.log("Invalid choice of chart"); break; } } console.log("End : initialize"); return loadIt; } catch (err) { console.error("Exception occurred in Home module: " + err.message); } } bindGlobalResize() { if (!GKChart.isResizeBound) { let resizeTimer; window.addEventListener("resize", () => { // 防抖:避免窗口拖动时频繁重绘 clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { // 遍历所有实例的重绘函数,逐一执行 GKChart.resizeHandlers.forEach(handler => handler()); console.warn("All charts resized successfully"); }, 250); }); GKChart.isResizeBound = true; } } // 可选:添加销毁方法,避免内存泄漏 destroy() { const handlerIndex = GKChart.resizeHandlers.indexOf(this.load); if (handlerIndex !== -1) { GKChart.resizeHandlers.splice(handlerIndex, 1); } // 这里可以添加其他清理逻辑,比如销毁图表实例、移除DOM元素等 } }
修复关键点说明
- 静态属性管理:用静态数组
resizeHandlers收集所有实例的重绘函数,确保resize时能遍历执行所有图表的重绘逻辑。 - 单次事件绑定:通过
isResizeBound标记,全局只绑定一次resize事件,避免重复绑定导致的性能损耗和逻辑冲突。 - 独立防抖定时器:把防抖定时器改成局部变量,不再使用全局的
window.resizeEvt,避免被后续实例覆盖。 - 可选的销毁方法:如果需要销毁某个图表实例,可以调用
destroy()方法从全局数组中移除对应的重绘函数,防止内存泄漏。
这样修改后,所有GKChart实例在窗口resize时都会触发重绘,完美解决你的问题!
内容的提问来源于stack exchange,提问作者Ganpat Kakar
相关产品推荐
相关产品推荐

