未关闭弹窗重复点击按钮时window["dataarray"]为undefined的问题
弹窗数据传递异常问题排查与修复
问题现象
点击按钮打开弹窗时,若每次打开前关闭已有弹窗,弹窗内可通过window["dataarray"]正常读取数据;但如果弹窗未关闭,再次点击其他按钮,弹窗内的window["dataarray"]会变为undefined——尽管主函数addTable里的v_popup["dataarray"]确实被赋值为sub_array。
弹窗内读取数据的代码:
window.onload = () => { addAnotherTable(window["dataarray"]); }
主函数代码:
function addTable(result, indices) { indices = [2, 3, 6, 2, 4, 4, 1, 5, 3, 1, 1, 1, 2, 4, 12, 1, 4, 4, 2, 1, 4, 1, 12, 13, 1, ]; //for testing counter = 0; low = []; high = []; for (var i = 0; i < indices.length; i++) { let btn = document.createElement("button"); btn.innerHTML = result[counter][0]; btn.className = "button-28"; var low = counter; var high = indices[i] + counter; var sub_array = result.slice(low, high); (function (sub_array) { btn.onclick = function () { var v_popup = window.open("popup.html", 'popUpWindow', 'height=300,width=700,left=50,top=50,resizable=no,scrollbars=no,toolbar=no,menubar=no,location=no,directories=no, status=no'); v_popup["dataarray"] = sub_array; } })(sub_array); counter += indices[i]; } }
原因分析
- 你调用
window.open时指定了固定窗口名popUpWindow,第二次点击按钮时,浏览器会复用已打开的弹窗窗口,并重新加载popup.html页面。 - 页面重新加载会清空原
window对象上的所有自定义属性(包括dataarray),而弹窗的window.onload触发时机早于主页面给新窗口赋值的时机,所以读取到undefined。 - 主函数里
v_popup["dataarray"]看似赋值成功,是因为window.open返回了复用的窗口对象,但此时弹窗页面已经开始刷新,后续赋值会随着页面重置而失效。
修复方案
方案一:每次新建独立弹窗
把窗口名改成动态唯一值(比如时间戳),避免复用旧窗口:
btn.onclick = function () { // 生成唯一窗口名,防止复用 const uniqueWindowName = 'popUpWindow_' + Date.now(); var v_popup = window.open("popup.html", uniqueWindowName, 'height=300,width=700,left=50,top=50,resizable=no,scrollbars=no,toolbar=no,menubar=no,location=no,directories=no, status=no'); v_popup["dataarray"] = sub_array; }
方案二:复用窗口并直接更新数据
如果需要保留单弹窗模式,不让页面刷新,直接调用弹窗内的方法更新数据:
- 主页面修改点击逻辑:
btn.onclick = function () { let v_popup = window.open('', 'popUpWindow', 'height=300,width=700,left=50,top=50,resizable=no,scrollbars=no,toolbar=no,menubar=no,location=no,directories=no, status=no'); if (v_popup.location.href === 'about:blank') { // 首次打开,加载页面并赋值 v_popup.location.href = "popup.html"; v_popup["dataarray"] = sub_array; } else { // 窗口已存在,直接调用弹窗内方法更新数据 if (typeof v_popup.addAnotherTable === 'function') { v_popup.addAnotherTable(sub_array); } else { // 防止页面未加载完成,延迟重试 setTimeout(() => { v_popup.addAnotherTable(sub_array); }, 100); } } }
- 弹窗页面修改代码,暴露方法供主页面调用:
// 弹窗页面核心逻辑 function addAnotherTable(data) { // 原有的数据处理逻辑 } // 把方法挂载到window,允许主页面直接调用 window.addAnotherTable = addAnotherTable; // 首次加载时仍兼容初始数据 window.onload = () => { if (window["dataarray"]) { addAnotherTable(window["dataarray"]); } }
方案三:通过URL参数传递数据(适合小数据量)
如果sub_array可以序列化为JSON,通过URL参数传递,页面刷新后也能读取:
- 主页面修改:
btn.onclick = function () { const dataStr = encodeURIComponent(JSON.stringify(sub_array)); var v_popup = window.open(`popup.html?data=${dataStr}`, 'popUpWindow', 'height=300,width=700,left=50,top=50,resizable=no,scrollbars=no,toolbar=no,menubar=no,location=no,directories=no, status=no'); }
- 弹窗页面读取数据:
window.onload = () => { const urlParams = new URLSearchParams(window.location.search); const dataStr = urlParams.get('data'); if (dataStr) { const dataarray = JSON.parse(decodeURIComponent(dataStr)); addAnotherTable(dataarray); } }
内容的提问来源于stack exchange,提问作者Mich
相关产品推荐
相关产品推荐

