如何简便创建全局/长期存活的google.visualization.DataTable()实例
google.visualization.DataTable 实例实现方法 官方示例里把DataTable写在加载回调的局部作用域内,纯粹是为了简化演示代码、避免额外的作用域传递逻辑,完全不代表DataTable本身不能作为全局实例长期存在。只要保证实例化动作发生在Charts库加载完成之后,创建的实例可以在回调执行结束后被任意位置的代码正常调用,没有任何机制限制它的生命周期。
具体实现方式
最简便的实现方式:提前声明全局变量占位,在加载回调中完成实例化
你不需要把DataTable的作用域锁死在回调函数内部,只要在全局作用域提前声明好用来存实例的变量,在加载完成的回调里把new出来的实例赋值给这个变量即可,回调执行结束后这个变量会一直保留实例的引用,可在任意位置读取、修改。
实际使用示例代码:// 全局作用域提前声明变量,初始为null占位 let sharedDataTable = null; // 常规加载Charts库的逻辑 google.charts.load('current', { packages: ['corechart'] }); google.charts.setOnLoadCallback(initTable); function initTable() { // 库加载完成后才实例化,避免构造函数未定义的错误 sharedDataTable = new google.visualization.DataTable(); // 正常初始化表结构,比如定义列 sharedDataTable.addColumn('string', '季度'); sharedDataTable.addColumn('number', '营收额'); // 可以在这里做初始数据填充 sharedDataTable.addRows([ ['第一季度', 1200], ['第二季度', 1800] ]); } // 后续任意位置的代码都可以直接使用这个全局实例 function updateTableData() { // 校验实例是否已经初始化完成后,就可以直接增删行 if (sharedDataTable) { sharedDataTable.addRow(['第三季度', 2100]); } }更可控的封装方式:单例缓存模式
如果不想暴露零散的全局变量,可以封装一个带缓存的获取方法,第一次调用时完成实例化,后续调用直接返回缓存的实例,减少全局作用域的污染:let tableInstanceCache = null; function getSharedDataTable() { // 校验缓存是否存在、Charts库是否已经加载完成 if (!tableInstanceCache && window.google?.visualization?.DataTable) { tableInstanceCache = new google.visualization.DataTable(); // 统一在这里做表结构初始化 tableInstanceCache.addColumn('string', '部门'); tableInstanceCache.addColumn('number', '人员数'); } return tableInstanceCache; }
关键注意点:所有
google.visualization.DataTable的实例化操作,必须发生在Google Charts库完全加载完成之后。如果在加载完成前就调用构造函数,会直接抛出google.visualization.DataTable is not a constructor的错误。
之所以官方示例没有演示全局实例的写法,是因为单页演示代码不需要处理跨函数的数据传递,把所有逻辑写在同一个回调里代码量最少,并不是设计上不支持长期存活。实际上DataTable本身的API设计(支持动态增删行列、可被多个图表实例绑定引用),本来就是适配长期存在、全局复用的场景的。
内容的提问来源于stack exchange,提问作者Michael Firth

