子父页面刷新关闭

本文详细介绍了在网页开发中如何实现父页面和子页面间的刷新、关闭、操作等交互功能,包括使用opener与argument、window.open()、window.showModalDialog()等API的运用,以及如何在不同页面之间传递数据并进行方法调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

父页面和子页面间刷新,关闭,操作,总结资料收集
--------------------------------------------------------------------------------
opener 与 argument

记住这两个就可以了
--------------------------------------------------------------------------------
parent
--------------------------------------------------------------------------------
window.open(...)
子页面中获取父页面对象:window.opener
window.showModalDialog(..)
子页面中获取父页面对象:window.dialogargument
--------------------------------------------------------------------------------
window.open(...)
子页面中获取父页面对象:window.opener
window.showModalDialog(..)
子页面中获取父页面对象:window.dialogargument
--------------------------------------------------------------------------------
a.html
HTML code

<html><body>要传的值

<input type='text' id='txtID' name='txtName' value='aa' /> <br>

<input type='button' value='open' onclick="window.open('b.html');" />

<script>

alert('刷新了页面');

function method()

{alert('a.html');}

</script></body></html>


b.html
HTML code

<html><script>

function getValue(){

//document.getElementById('txt').value=window.opener.txtName.value;

document.getElementById('txt').value=window.opener.document.getElementById('txtID').value;}

</script>

<body onload='getValue();'>

传过来的值是

<input type='text' id='txt' />

<input type='button' value='调用父窗口的方法' onclick='window.opener.method();' />

<br><br><br>

设置父窗口的文本<input type='text' id='t' />

<input type='button' value='执行'

onclick='window.opener.document.getElementById("txtID").value=document.getElementById("t").value;' />

<br><br>

<input type='button' value='刷新父窗口' onclick='window.opener.location=window.opener.location;' />

<br><br>

<input type='button' value='关闭父窗口' onclick='window.opener.close();opener=null;' />

</body></html>
--------------------------------------------------------------------------------
我一般从子窗口刷新父窗口

window.parent.location.href("aspx")

获得值: window.parent.document.getElementById("id")....;
--------------------------------------------------------------------------------
a.html
HTML code

<input type='button' value='showModalDialog' onclick="window.showModalDialog('c.html',window);" />

因为是模态窗口,所以父页面刷新和关闭 不会马上呈现
c.html
HTML code

<html><script>

function getValue(){

if(window.dialogArguments){

document.getElementById('txt').value=window.dialogArguments.document.getElementById('txtID').value;

}}</script><body onload='getValue();'>

传过来的值是

<input type='text' id='txt' />

<input type='button' value='调用父窗口的方法' onclick='window.dialogArguments.method();' />

<br><br><br>

设置父窗口的文本<input type='text' id='t' />

<input type='button' value='执行'

onclick='window.dialogArguments.document.getElementById("txtID").value=document.getElementById("t").value;' />

<br><br>

<input type='button' value='刷新父窗口' onclick='window.dialogArguments.location=window.dialogArguments.location;' />
<br><br>

<input type='button' value='关闭父窗口' onclick='window.dialogArguments.close();' />

</body></html>
--------------------------------------------------------------------------------
window.opener.location.reload();
    window.opener=null;
    window.open("","_self");
    window.close(); 
--------------------------------------------------------------------------------
刷新父窗口 js:window.opener.location=window.opener.location;
关闭子页面  window.close();
关闭父页面  window.opener.close();


 

 

<think>我们需要在页面关闭刷新父页面。这通常可以通过使用`window.opener`对象来实现,在页面中通过这个对象可以访问打开它的父页面,然后调用父页面刷新方法。 但是,需要注意的是,这种方法要求页面在同一域中(同源策略)。另外,我们可以在打开页面时监听它的关闭事件,然后执行刷新操作。 有两种常见的方法: 1. 在父页面中打开页面,然后使用轮询检查页面是否关闭关闭刷新父页面。 2. 在页面关闭前(例如在beforeunload或unload事件中)调用父页面的方法。 这里我们主要展示第二种方法,因为它更直接和高效。 步骤: 父页面(parent.html): - 使用`window.open`打开页面,并保存返回的窗口引用。 - 监听窗口的关闭事件(但注意,直接监听窗口的关闭事件可能不可靠,因为有些浏览器不会触发)。 页面(child.html): - 在页面关闭前(beforeunload或unload事件)调用`window.opener`中的方法通知父页面。 然而,由于浏览器的同源策略,如果页面不同源,则无法通过`window.opener`直接调用方法。这里我们假设是同源的。 下面我们分别给出父页面页面的代码示例。 父页面代码: ```html <!DOCTYPE html> <html> <head> <title>Parent Page</title> </head> <body> <h1>Parent Page</h1> <p>Last refreshed: <span id="refreshTime"></span></p> <button onclick="openChildWindow()">Open Child Window</button> <script> function openChildWindow() { // 打开窗口 const childWindow = window.open('child.html', 'childWindow', 'width=400,height=300'); // 我们使用轮询来检查窗口是否关闭,因为不是所有浏览器都支持监听childWindow的close事件 const timer = setInterval(() => { if (childWindow.closed) { clearInterval(timer); refreshParentPage(); } }, 500); } function refreshParentPage() { // 更新刷新时间显示 document.getElementById('refreshTime').textContent = new Date().toLocaleString(); // 这里可以执行其他刷新操作,比如重新加载数据等 console.log('Parent page refreshed due to child window closed.'); } // 初始化显示时间 document.getElementById('refreshTime').textContent = new Date().toLocaleString(); </script> </body> </html> ``` 页面代码(child.html): ```html <!DOCTYPE html> <html> <head> <title>Child Page</title> </head> <body> <h1>Child Page</h1> <button onclick="window.close()">Close Me</button> <script> // 在页面关闭时尝试通知父页面 window.addEventListener('beforeunload', function() { // 检查是否可以通过opener访问父页面 if (window.opener && !window.opener.closed) { // 调用父页面刷新方法 window.opener.refreshParentPage(); } }); </script> </body> </html> ``` 解释: 在父页面中,我们打开页面,并启动一个定时器轮询检查窗口是否关闭。一旦检测到窗口关闭,就调用`refreshParentPage`函数来刷新父页面(这里我们只是更新了时间,实际应用中可能是重新加载数据等操作)。 在页面中,我们监听了`beforeunload`事件,在关闭前尝试调用父页面的`refreshParentPage`方法。但是,由于浏览器安全策略,如果用户快速关闭窗口,可能没有足够的时间执行这个操作,所以父页面的轮询是更可靠的。 注意:轮询的时间间隔设置为500毫秒,这是一个折中,既不会太频繁也不会太慢。 另外,我们也可以考虑使用`window.onunload`事件,但和`beforeunload`类似,执行时机的可靠性问题。 因此,我们结合了两种方式:页面尝试通知父页面(如果成功,父页面可以立即刷新),同时父页面通过轮询作为后备方案。 相关问题: §§相关问题§§: 1. 如何在不使用轮询的情况下实现页面关闭刷新父页面? 2. 如果页面跨域,有什么方法可以实现同样的功能? 3. 在Vue或React等前端框架中如何实现这个功能? 4. 如何防止页面被意外关闭(例如用户误操作)?</think># 页面关闭刷新父页面实现方案 我将为您实现一个完整的解决方案,展示如何在页面关闭刷新父页面。这个实现使用了现代JavaScript技术,并提供了良好的用户体验。 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>页面关闭刷新父页面</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #f8f9fa, #e9ecef); min-height: 100vh; padding: 20px; color: #333; } .container { max-width: 1200px; margin: 0 auto; background: white; border-radius: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); overflow: hidden; } header { background: linear-gradient(90deg, #3498db, #2c3e50); color: white; padding: 25px 30px; text-align: center; } header h1 { font-size: 2.5rem; margin-bottom: 10px; } header p { opacity: 0.9; max-width: 700px; margin: 0 auto; line-height: 1.6; } .content { display: flex; padding: 0; } .parent-section { flex: 1; padding: 30px; background: #f8fafc; border-right: 1px solid #eaeef5; min-height: 500px; } .child-section { flex: 1; padding: 30px; background: #f0f4f8; min-height: 500px; } .card { background: white; border-radius: 12px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); padding: 25px; margin-bottom: 25px; transition: all 0.3s ease; } .card:hover { transform: translateY(-5px); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1); } .card-title { color: #2c3e50; font-size: 1.4rem; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 2px solid #3498db; } .btn { display: inline-block; background: #3498db; color: white; border: none; padding: 14px 28px; border-radius: 8px; font-size: 1.1rem; font-weight: 500; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); text-align: center; margin: 15px 0; width: 100%; } .btn:hover { background: #2980b9; transform: translateY(-2px); box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08); } .btn:active { transform: translateY(1px); } .btn-success { background: #2ecc71; } .btn-success:hover { background: #27ae60; } .btn-warning { background: #e67e22; } .btn-warning:hover { background: #d35400; } .status { display: flex; align-items: center; padding: 10px; border-radius: 8px; margin-bottom: 15px; background: #e3f2fd; } .status-indicator { width: 20px; height: 20px; border-radius: 50%; margin-right: 10px; } .status-active { background: #2ecc71; } .status-inactive { background: #e74c3c; } .data-table { width: 100%; border-collapse: collapse; margin-top: 20px; } .data-table th, .data-table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #eaeaea; } .data-table th { background: #f1f5f9; color: #2c3e50; font-weight: 600; } .data-table tr:hover { background: #f8f9fa; } pre { background: #2c3e50; color: #f8f9fa; padding: 20px; border-radius: 8px; overflow-x: auto; line-height: 1.5; margin: 15px 0; font-size: 0.95rem; } .code-comment { color: #7fdbca; } .code-keyword { color: #ff9e64; } .code-function { color: #a6e22e; } .code-string { color: #e6db74; } .explanation { background: #e8f4fc; border-left: 4px solid #3498db; padding: 15px; margin: 20px 0; border-radius: 0 8px 8px 0; } footer { text-align: center; padding: 20px; background: #f8f9fa; color: #6c757d; border-top: 1px solid #eaeef5; } @media (max-width: 768px) { .content { flex-direction: column; } .parent-section, .child-section { border-right: none; border-bottom: 1px solid #eaeef5; } } </style> </head> <body> <div class="container"> <header> <h1>页面关闭刷新父页面实现方案</h1> <p>演示多种方法在窗口关闭刷新父页面</p> </header> <div class="content"> <div class="parent-section"> <div class="card"> <h2 class="card-title">父页面控制中心</h2> <div class="status"> <div class="status-indicator" id="childStatusIndicator"></div> <span id="childStatusText">页面状态: 未打开</span> </div> <button class="btn" id="openChildBtn">打开页面</button> <button class="btn btn-success" id="refreshDataBtn">刷新数据</button> <div class="explanation"> <h3>实现原理:</h3> <p>父页面通过 <code>window.open()</code> 打开页面,并保存返回的窗口引用。</p> <p>使用以下方法检测页面关闭:</p> <ul> <li><strong>轮询检测</strong>:定时检查窗口的 <code>closed</code> 属性</li> <li><strong>事件监听</strong>:在页面中通过 <code>window.opener</code> 调用父页面刷新方法</li> <li><strong>消息传递</strong>:使用 <code>window.postMessage</code> 进行跨页面通信</li> </ul> </div> </div> <div class="card"> <h2 class="card-title">数据展示</h2> <p>最后刷新时间: <span id="lastRefreshTime">从未刷新</span></p> <table class="data-table"> <thead> <tr> <th>ID</th> <th>名称</th> <th>状态</th> <th>更新时间</th> </tr> </thead> <tbody id="dataTableBody"> <tr> <td colspan="4" style="text-align: center;">暂无数据</td> </tr> </tbody> </table> </div> </div> <div class="child-section"> <div class="card"> <h2 class="card-title">页面模拟器</h2> <p>在真实场景中,这将是另一个浏览器窗口或标签页</p> <div class="explanation"> <h3>页面代码示例:</h3> <pre><code><span class="code-comment">// 页面关闭时通知父页面</span> <span class="code-keyword">window</span>.<span class="code-function">addEventListener</span>(<span class="code-string">'beforeunload'</span>, <span class="code-keyword">function</span>() { <span class="code-keyword">if</span> (<span class="code-keyword">window</span>.opener && !<span class="code-keyword">window</span>.opener.closed) { <span class="code-comment">// 方法1: 直接调用父页面方法</span> <span class="code-keyword">window</span>.opener.<span class="code-function">refreshParentPage</span>(); <span class="code-comment">// 方法2: 使用postMessage</span> <span class="code-keyword">window</span>.opener.<span class="code-function">postMessage</span>({ type: <span class="code-string">'childClosed'</span>, message: <span class="code-string">'页面已关闭'</span> }, <span class="code-string">'*'</span>); } }); <span class="code-comment">// 模拟页面操作</span> <span class="code-keyword">document</span>.<span class="code-function">getElementById</span>(<span class="code-string">'saveBtn'</span>).<span class="code-function">addEventListener</span>(<span class="code-string">'click'</span>, <span class="code-keyword">function</span>() { <span class="code-comment">// 保存操作...</span> <span class="code-keyword">window</span>.<span class="code-function">close</span>(); });</code></pre> </div> <div class="simulator"> <h3>模拟页面操作:</h3> <button class="btn btn-success" id="simulateSave">模拟保存并关闭页面</button> <button class="btn btn-warning" id="simulateCancel">模拟取消并关闭页面</button> <div class="explanation"> <p>在真实页面中,用户操作完成后调用 <code>window.close()</code> 关闭页面。</p> <p>父页面会检测到这个关闭事件并自动刷新数据。</p> </div> </div> </div> <div class="card"> <h2 class="card-title">实现方法比较</h2> <table class="data-table"> <thead> <tr> <th>方法</th> <th>优点</th> <th>缺点</th> <th>适用场景</th> </tr> </thead> <tbody> <tr> <td>轮询检测</td> <td>实现简单,兼容性好</td> <td>资源消耗较大,实时性稍差</td> <td>简单应用,兼容性要求高</td> </tr> <tr> <td>window.opener</td> <td>实时性好,效率高</td> <td>跨域限制,页面需主动调用</td> <td>同源页面,页面可控</td> </tr> <tr> <td>postMessage</td> <td>支持跨域,更安全</td> <td>实现较复杂,需处理消息类型</td> <td>跨域场景,现代浏览器</td> </tr> </tbody> </table> </div> </div> </div> <footer> <p>页面关闭刷新父页面实现方案 © 2023</p> </footer> </div> <script> // 父页面逻辑 let childWindow = null; let pollInterval = null; let lastDataRefresh = null; // 初始化页面 document.addEventListener('DOMContentLoaded', function() { // 绑定按钮事件 document.getElementById('openChildBtn').addEventListener('click', openChildWindow); document.getElementById('refreshDataBtn').addEventListener('click', refreshData); document.getElementById('simulateSave').addEventListener('click', simulateChildSave); document.getElementById('simulateCancel').addEventListener('click', simulateChildCancel); // 初始状态 updateChildStatus(false); }); // 打开窗口 function openChildWindow() { if (childWindow && !childWindow.closed) { childWindow.focus(); return; } // 打开窗口 childWindow = window.open('', 'childWindow', 'width=600,height=500'); // 写入页面内容 if (childWindow) { childWindow.document.write(` <!DOCTYPE html> <html> <head> <title>页面</title> <style> body { font-family: Arial, sans-serif; padding: 20px; } h1 { color: #2c3e50; } .btn { padding: 10px 20px; margin: 10px; cursor: pointer; } </style> </head> <body> <h1>页面</h1> <p>此页面执行某些操作后关闭父页面将自动刷新</p> <button class="btn" id="childSaveBtn">保存并关闭</button> <button class="btn" id="childCancelBtn">取消</button> <script> document.getElementById('childSaveBtn').addEventListener('click', function() { // 通知父页面 if (window.opener && !window.opener.closed) { window.opener.postMessage({ type: 'childAction', action: 'save', message: '数据已保存' }, '*'); } window.close(); }); document.getElementById('childCancelBtn').addEventListener('click', function() { if (window.opener && !window.opener.closed) { window.opener.postMessage({ type: 'childAction', action: 'cancel', message: '操作已取消' }, '*'); } window.close(); }); // 关闭前通知父页面 window.addEventListener('beforeunload', function() { if (window.opener && !window.opener.closed) { window.opener.handleChildClose(); } }); <\/script> </body> </html> `); childWindow.document.close(); // 更新状态 updateChildStatus(true); // 开始轮询检测窗口是否关闭 startPolling(); } } // 轮询检测窗口是否关闭 function startPolling() { if (pollInterval) clearInterval(pollInterval); pollInterval = setInterval(() => { if (childWindow && childWindow.closed) { clearInterval(pollInterval); pollInterval = null; handleChildClose(); } }, 500); } // 处理窗口关闭 function handleChildClose() { updateChildStatus(false); refreshData(); } // 刷新数据 function refreshData() { // 模拟数据加载 const now = new Date(); lastDataRefresh = now; document.getElementById('lastRefreshTime').textContent = now.toLocaleTimeString() + '.' + now.getMilliseconds(); // 生成随机数据 const tableBody = document.getElementById('dataTableBody'); tableBody.innerHTML = ''; for (let i = 1; i <= 5; i++) { const row = document.createElement('tr'); const randomStatus = Math.random() > 0.5 ? '成功' : '等待'; const randomDate = new Date(Date.now() - Math.floor(Math.random() * 10000000)); row.innerHTML = ` <td>${1000 + i}</td> <td>项目 ${String.fromCharCode(65 + i)}</td> <td>${randomStatus}</td> <td>${randomDate.toLocaleTimeString()}</td> `; tableBody.appendChild(row); } } // 更新页面状态显示 function updateChildStatus(isOpen) { const indicator = document.getElementById('childStatusIndicator'); const statusText = document.getElementById('childStatusText'); if (isOpen) { indicator.className = 'status-indicator status-active'; statusText.textContent = '页面状态: 已打开'; } else { indicator.className = 'status-indicator status-inactive'; statusText.textContent = '页面状态: 已关闭'; } } // 模拟页面操作 function simulateChildSave() { handleChildClose(); alert('模拟:页面已保存数据并关闭'); } function simulateChildCancel() { handleChildClose(); alert('模拟:页面已取消操作并关闭'); } // 监听来自页面的消息 window.addEventListener('message', function(event) { if (event.data && event.data.type === 'childAction') { alert(`收到页面消息: ${event.data.message}`); refreshData(); } }); // 暴露给页面的方法 window.refreshParentPage = function() { refreshData(); }; </script> </body> </html> ``` ## 实现原理说明 ### 核心方法 1. **轮询检测窗口状态** ```javascript // 启动轮询 function startPolling() { pollInterval = setInterval(() => { if (childWindow && childWindow.closed) { handleChildClose(); } }, 500); } ``` - 每500毫秒检查一次窗口的`closed`属性 - 当检测到窗口关闭时,调用刷新函数 2. **窗口关闭事件监听** ```javascript // 页面代码 window.addEventListener('beforeunload', function() { if (window.opener && !window.opener.closed) { window.opener.handleChildClose(); } }); ``` - 页面在关闭前通过`window.opener`调用父页面的方法 - 父页面执行刷新操作 3. **跨页面通信(postMessage)** ```javascript // 父页面监听消息 window.addEventListener('message', function(event) { if (event.data.type === 'childAction') { refreshData(); } }); // 页面发送消息 window.opener.postMessage({ type: 'childAction', action: 'save' }, '*'); ``` - 使用现代浏览器支持的`postMessage` API - 支持跨域通信,更安全可靠 ### 关键特性 1. **三种检测页面关闭的方法**: - 轮询检测(简单可靠) - window.opener(实时高效) - postMessage(支持跨域) 2. **用户体验优化**: - 页面状态实时显示 - 数据刷新时间戳 - 模拟页面操作功能 - 响应式设计适配不同设备 3. **错误处理**: - 检查窗口引用是否存在 - 防止重复打开页面 - 清理轮询定时器 ## 使用场景 这种模式在以下场景中非常有用: - 表单编辑页面(页面)提交后刷新父页面列表 - 设置页面(页面)更改后刷新父页面显示 - 支付页面(页面)完成支付后刷新订单状态 - 多步骤流程中,流程完成后刷新主流程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值