子页面和dialog案例

bash 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子HTML弹窗 与 弹框 传参demo(单文件)</title>
<style>
  :root{
    --primary:#4f6ef7;
    --primary-dark:#3b55d9;
    --bg:#f4f6fb;
    --card:#ffffff;
    --text:#1f2430;
    --text-secondary:#6b7280;
    --border:#e5e7eb;
    --success-bg:#eafaf0;
    --success-text:#1a7f4e;
    --radius:14px;
  }
  *{box-sizing:border-box;}
  body{
    margin:0;
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
    background:var(--bg);
    color:var(--text);
    padding:40px 20px;
  }
  .container{max-width:760px;margin:0 auto;}
  h1{font-size:24px;font-weight:600;margin:0 0 6px;}
  .subtitle{color:var(--text-secondary);font-size:14px;margin:0 0 32px;}

  .grid{display:grid;grid-template-columns:1fr 1fr;gap:20px;}
  @media(max-width:640px){.grid{grid-template-columns:1fr;}}

  .card{
    background:var(--card);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:24px;
    display:flex;
    flex-direction:column;
    gap:14px;
    box-shadow:0 1px 3px rgba(0,0,0,0.04);
  }
  .card h2{font-size:16px;margin:0;display:flex;align-items:center;gap:8px;}
  .card p{font-size:13px;color:var(--text-secondary);margin:0;line-height:1.6;flex:1;}
  .badge{
    display:inline-block;
    font-size:11px;
    padding:3px 8px;
    border-radius:999px;
    background:#eef1ff;
    color:var(--primary-dark);
    width:fit-content;
  }

  button.action{
    background:var(--primary);
    color:#fff;
    border:none;
    border-radius:10px;
    padding:10px 16px;
    font-size:14px;
    cursor:pointer;
    transition:background .15s ease, transform .1s ease;
  }
  button.action:hover{background:var(--primary-dark);}
  button.action:active{transform:scale(0.98);}

  .result-box{
    margin-top:28px;
    background:var(--card);
    border:1px solid var(--border);
    border-radius:var(--radius);
    padding:20px 24px;
  }
  .result-box h3{font-size:14px;margin:0 0 12px;color:var(--text-secondary);font-weight:500;}
  .result-item{
    display:none;
    align-items:center;
    gap:10px;
    background:var(--success-bg);
    color:var(--success-text);
    padding:10px 14px;
    border-radius:10px;
    font-size:13px;
    margin-bottom:8px;
  }
  .result-item.show{display:flex;}
  .result-empty{font-size:13px;color:var(--text-secondary);}

  /* ---- 弹框(模态对话框)样式 ---- */
  dialog{
    border:none;
    border-radius:16px;
    padding:0;
    width:min(380px,92vw);
    box-shadow:0 20px 60px rgba(0,0,0,0.18);
  }
  dialog::backdrop{background:rgba(20,20,30,0.35);}
  .modal-inner{padding:24px;}
  .modal-inner h3{margin:0 0 4px;font-size:17px;}
  .modal-inner .modal-sub{font-size:13px;color:var(--text-secondary);margin:0 0 18px;}
  .field{margin-bottom:14px;}
  .field label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:6px;}
  .field input{
    width:100%;
    padding:9px 12px;
    border:1px solid var(--border);
    border-radius:8px;
    font-size:14px;
    outline:none;
  }
  .field input:focus{border-color:var(--primary);}
  .modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px;}
  button.ghost{
    background:transparent;
    border:1px solid var(--border);
    border-radius:10px;
    padding:9px 16px;
    font-size:14px;
    cursor:pointer;
    color:var(--text);
  }
  button.ghost:hover{background:#f3f4f6;}

  /* ---- 代码片段展示 ---- */
  pre.code{
    background:#1e2230;
    color:#e3e6f0;
    border-radius:10px;
    padding:14px 16px;
    font-size:12.5px;
    line-height:1.6;
    overflow-x:auto;
    margin:0;
    font-family:"SFMono-Regular",Consolas,"Courier New",monospace;
  }
  pre.code .kw{color:#7aa2f7;}
  pre.code .fn{color:#c0caf5;}
  pre.code .str{color:#9ece6a;}
  pre.code .com{color:#6b7280;}
</style>
</head>
<body>
<div class="container">
  <h1>主页面(单文件demo)</h1>
  <p class="subtitle">演示两种向主页面传参的方式:弹出子HTML窗口 vs 页内弹框,全部写在同一个 html 文件里</p>

  <div class="grid">
    <div class="card">
      <span class="badge">window.open</span>
      <h2>① 打开子HTML页面</h2>
      <p>点击后用 Blob 动态生成一个独立子页面并以弹出窗口形式打开(不是新标签页)。在子页面填写信息提交后,通过 postMessage 把数据传回本页面,随后子窗口自动关闭。</p>
      <button class="action" id="openChildBtn">打开子页面</button>
      <pre class="code"><span class="com">// 子页面:打开弹出窗口</span>
<span class="kw">const</span> url = URL.createObjectURL(blob);
<span class="fn">window.open</span>(url, <span class="str">'childWindow'</span>,
  <span class="str">'width=380,height=380'</span>);

<span class="com">// 子页面:把数据传回主页面</span>
window.opener.<span class="fn">postMessage</span>(
  { type: <span class="str">'CHILD_SUBMIT'</span>, payload: data },
  <span class="str">'*'</span>
);

<span class="com">// 主页面:接收数据</span>
window.<span class="fn">addEventListener</span>(<span class="str">'message'</span>, e => {
  <span class="kw">const</span> data = e.data.payload;
});</pre>
    </div>

    <div class="card">
      <span class="badge">&lt;dialog&gt;</span>
      <h2>② 打开弹框</h2>
      <p>点击后在当前页面内弹出模态对话框,不产生新窗口。填写并提交后直接调用主页面函数拿到数据。</p>
      <button class="action" id="openModalBtn">打开弹框</button>
      <pre class="code"><span class="com">// HTML:弹框本体,与主页面同属一个DOM</span>
&lt;<span class="kw">dialog</span> id=<span class="str">"myModal"</span>&gt;...&lt;/<span class="kw">dialog</span>&gt;

<span class="com">// 打开弹框</span>
modal.<span class="fn">showModal</span>();

<span class="com">// 提交时直接读取同页面的表单值</span>
form.<span class="fn">addEventListener</span>(<span class="str">'submit'</span>, e => {
  <span class="kw">const</span> name = nameInput.value;
  <span class="com">// 无需跨窗口通信,直接使用</span>
});</pre>
    </div>
  </div>

  <div class="result-box">
    <h3>接收到的数据</h3>
    <div class="result-item" id="childResult"></div>
    <div class="result-item" id="modalResult"></div>
    <p class="result-empty" id="emptyTip">暂无数据,试试上面两个按钮</p>
  </div>
</div>

<!-- 弹框(模态对话框)本体,与主页面同属一个DOM -->
<dialog id="myModal">
  <div class="modal-inner">
    <h3>填写信息(弹框)</h3>
    <p class="modal-sub">提交后数据直接传回主页面,不会离开当前页面</p>
    <form id="modalForm" method="dialog">
      <div class="field">
        <label>姓名</label>
        <input type="text" id="modalName" required placeholder="请输入姓名">
      </div>
      <div class="field">
        <label>备注</label>
        <input type="text" id="modalNote" placeholder="选填">
      </div>
      <div class="modal-actions">
        <button type="button" class="ghost" id="cancelModal">取消</button>
        <button type="submit" class="action">提交</button>
      </div>
    </form>
  </div>
</dialog>

<script>
  var emptyTip = document.getElementById('emptyTip');
  var childResult = document.getElementById('childResult');
  var modalResult = document.getElementById('modalResult');

  function showResult(el, text){
    el.textContent = text;
    el.classList.add('show');
    emptyTip.style.display = 'none';
  }

  // ---- ① 打开子HTML页面(弹出窗口,用 Blob 动态生成,不需要单独的 html 文件) ----
  document.getElementById('openChildBtn').addEventListener('click', function(){
    var childHtml = [
      '<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8">',
      '<title>子页面</title>',
      '<style>',
      'body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#fff;color:#1f2430;padding:22px;}',
      'h2{font-size:16px;margin:0 0 4px;}',
      '.sub{font-size:12px;color:#6b7280;margin:0 0 18px;}',
      '.field{margin-bottom:14px;}',
      '.field label{display:block;font-size:12px;color:#6b7280;margin-bottom:6px;}',
      '.field input{width:100%;padding:9px 12px;border:1px solid #e5e7eb;border-radius:8px;font-size:14px;box-sizing:border-box;outline:none;}',
      '.field input:focus{border-color:#4f6ef7;}',
      '.actions{display:flex;justify-content:flex-end;gap:8px;margin-top:20px;}',
      'button{border-radius:10px;padding:9px 16px;font-size:14px;cursor:pointer;border:1px solid #e5e7eb;background:#fff;color:#1f2430;}',
      'button.primary{background:#4f6ef7;color:#fff;border:none;}',
      'button.primary:hover{background:#3b55d9;}',
      'button:hover{background:#f3f4f6;}',
      '</style></head><body>',
      '<h2>我是子HTML页面</h2>',
      '<p class="sub">这是一个独立的弹出窗口,提交后会把数据传回打开它的主页面</p>',
      '<form id="childForm">',
      '<div class="field"><label>姓名</label><input type="text" id="name" required placeholder="请输入姓名"></div>',
      '<div class="field"><label>邮箱</label><input type="email" id="email" required placeholder="请输入邮箱"></div>',
      '<div class="actions"><button type="button" id="closeBtn">取消</button><button type="submit" class="primary">提交并关闭</button></div>',
      '</form>',
      '<script>',
      'document.getElementById("closeBtn").addEventListener("click", function(){ window.close(); });',
      'document.getElementById("childForm").addEventListener("submit", function(e){',
      '  e.preventDefault();',
      '  var data = { name: document.getElementById("name").value, email: document.getElementById("email").value };',
      '  if(window.opener){ window.opener.postMessage({ type: "CHILD_SUBMIT", payload: data }, "*"); }',
      '  window.close();',
      '});',
      '<\/script>',
      '</body></html>'
    ].join('');

    var blob = new Blob([childHtml], { type: 'text/html' });
    var url = URL.createObjectURL(blob);
    // width/height 等参数是让浏览器以"弹出窗口"而非"新标签页"打开的关键
    window.open(url, 'childWindow', 'width=380,height=380,left=200,top=150');
  });

  // 监听子窗口通过 postMessage 传回的数据
  window.addEventListener('message', function(event){
    if(event.data && event.data.type === 'CHILD_SUBMIT'){
      var d = event.data.payload;
      showResult(childResult, '来自子页面: 姓名=' + d.name + ', 邮箱=' + d.email);
    }
  });

  // ---- ② 弹框(模态对话框) ----
  var modal = document.getElementById('myModal');
  document.getElementById('openModalBtn').addEventListener('click', function(){
    modal.showModal();
  });
  document.getElementById('cancelModal').addEventListener('click', function(){
    modal.close();
  });
  document.getElementById('modalForm').addEventListener('submit', function(e){
    var name = document.getElementById('modalName').value;
    var note = document.getElementById('modalNote').value;
    showResult(modalResult, '来自弹框: 姓名=' + name + (note ? ', 备注=' + note : ''));
    document.getElementById('modalForm').reset();
  });
</script>
</body>
</html>
相关推荐
小月土星9 小时前
(实战篇)RAG-demo 深度解析:162行代码中的检索增强生成全景 (含Top-k法)
javascript·数据库·llm
倒流时光三十年9 小时前
Logback 系列(3):三大核心组件 Logger / Appender / Encoder
java·开发语言·logback
Darkwanderor9 小时前
动、静态库相关内容的详细介绍
linux·c语言·开发语言·c++
文祐9 小时前
C++类之虚函数表没有虚继承的菱形继承
开发语言·c++·算法
lvchaoq9 小时前
this指向面试代码输出题目合集
javascript·面试·职场和发展
sycmancia10 小时前
Qt——另一种创建线程的方式
开发语言·qt
你怎么知道我是队长10 小时前
JavaScript 函数 this 全解
开发语言·javascript·ecmascript
L-影10 小时前
单体项目结构
java·开发语言
孬甭_11 小时前
C++ string类
开发语言·c++