onclick内初始化的全局变量ClickedChillerName外部访问为何返回undefined
问题核心根因
代码中存在的3个确定性错误
- 变量作用域认知错位:你注释掉了
ClickedChillerName的声明,即便放开注释,写在window.onload回调内部的var变量属于onload函数的局部作用域,根本不是全局可访问的变量,作用域外的逻辑无法正常读取。 - 事件回调执行顺序颠倒:在
$(".tsi-name").click的回调中,你第一行就执行了window.location.reload()。浏览器接收到reload指令后会立刻终止当前页面所有后续JS执行流程,开始重载动作,回调里后续的ClickedChillerName=this.innerHTML、相关日志打印代码根本不会被执行,哪怕不跨重载都拿不到赋值。 - 页面重载机制认知偏差:页面重载会完全清空浏览器内存中存储的所有JS运行时状态,包括全局变量、局部变量、闭包内的所有赋值。哪怕你真的把变量挂到window对象上,重载完成后所有JS状态都会回到脚本首次加载的初始值,不可能跨重载保留上次点击的赋值结果。
可落地的修正方案
1. 调整执行顺序,优先存储业务值
将点击回调内的赋值、存储逻辑放在重载动作之前,避免执行流程被中断。
2. 用浏览器持久化存储实现跨重载的值传递
因为纯JS变量无法在重载后保留状态,需要借助浏览器提供的存储API(优先用sessionStorage,关闭标签页自动清理,不残留无效数据)存取值:
- 点击事件触发时,把当前点击的ChillerName值存入
sessionStorage - 页面重载完成、onload触发时,再从
sessionStorage中读取之前存的值,替代原来直接读JS变量的逻辑
修正后的核心代码示例
window.onload = function() { initAuth('Line chart and events table using the PAYG SKU'); const tsiClient = new TsiClient(); const linechartTsqExpressions = []; const startDate = new Date('2021-01-27T04:20:00Z'); const endDate = new Date(startDate.valueOf() + 1000*60*60*4); // 从sessionStorage读取之前点击存入的值,取不到给空字符串兜底 const ClickedChillerName = sessionStorage.getItem('clickedChillerName') || ''; console.log("step4" + ClickedChillerName); linechartTsqExpressions.push(new tsiClient.ux.TsqExpression({timeSeriesId: [ClickedChillerName]}, {Max: { kind: 'numeric', value: {tsx: '$event.temperature.Double'}, filter: null, aggregation: {tsx: 'max($value)'} }}, { from: startDate, to: endDate, bucketSize: '1m' }, '#60B9AE', 'MaxValue')); var onInstanceClick = function(instance) { $(".tsi-name").click(function() { const currentChillerName = this.innerHTML.trim(); // 先存值,再触发重载 sessionStorage.setItem('clickedChillerName', currentChillerName); window.location.reload(); }); // 其余原有异步逻辑保持不变 let contextMenuActions = []; authContext.getTsiToken() .then(token => { tsiClient.server.getTimeseriesTypes(token, 'Test.env.timeseries.azure.com', [instance.type.id]) .then(r => { if (r.get && Array.isArray(r.get)) { r.get.forEach((t) => { let type = t.timeSeriesType; Object.keys(type.variables).forEach((vName) => { let option = {}; if (type.variables[vName].aggregation.tsx === 'avg($value)') { let newType = this.getTsmTypeFromVariable(type.variables[vName]); option['name'] = vName; option['action'] = () => addInstanceAction(newType, vName, instance); } else { option['name'] = vName; option['action'] = () => addInstanceAction(instance.type, vName, instance); } contextMenuActions.push(option); }); }); hierarchy.drawContextMenu(contextMenuActions, {}); } }) }); } }
额外注意事项
- 不要把变量声明在onload内部就当成全局变量,真要全局可访问的变量需要手动挂载到window对象,比如
window.ClickedChillerName = xxx,但即便这样也无法跨重载保留值。 - 点击事件的绑定不要写在onInstanceClick内部重复注册,否则多次触发实例渲染后会出现同一个元素绑定多个重复click回调的问题,建议把事件绑定抽离到全局公共逻辑区。
内容的提问来源于stack exchange,提问作者Anusha
相关产品推荐
相关产品推荐

