iframe内嵌页弹窗随着外层的滚动位置有效显示

625 阅读1分钟

场景介绍

我们的的项目比较宠大,集成多个大模块,大模块下面又分多个小模块 。项目是协同开发,有多个项目组,每一个项目是独立运行开发的。系统集成在一个总端,总端进行登录管理,主题框架、路由管理。页面结构上中下,上是主模块导航,中又分为左导航,右内容展示。现在项目进行重构 ,内容展示是iframe。原来是用c#进行的开发,现在实现前后端分离,前端使用vue element-ui。老的页面alert、confirm、在iframe 触发时在窗体正中上方展示,现如今如果在页面滚动比较底部的时候 alert就不能够正常展示了。因为alert 就不能够正常展示了 。因为alert 是相对于iframe的窗体居中显示的 ,在主题框架外部进行了iframe高度设置,会随着外部的滚动进行页面展示。

解决办法

我们就用2个页面进行场景模拟,父页面和子页面 ,子页面是通过父页面iframe 引起来的。

父页面代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{
      padding: 0;
      margin: 0;
    }
    .main{
      display: flex;
    }
    .left{
      width: 200px;
      background: #ccc;
      height: 300px;
    }
    #iframe{
      width: 100%;
    }
  </style>
  <script>
    function callback(){
      var iframe = document.getElementById('iframe');
      var height = iframe.contentDocument.body.scrollHeight
      iframe.style.height = height +"px"
      console.log(height)
    }
    window.onload=function(){
      callback()
    }
    // document.onload=function(){
    //   callback()

    // }
  </script>
</head>
<body>
  <div style="height:200px;background:blue"></div>
  <div class="main">
    <div class="left"></div>

    <iframe id="iframe" src="./son.html" ></iframe>

  </div>
  
</body>
</html>

子页面代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{
      padding: 0;
      margin: 0;
    }
    .box{
      background: red;
      height: 2000px;
      overflow: hidden;
    }
    .btn1{
      display: block;
      margin-top: 500px;
    }
    .btn2{
      display: block;
      margin-top: 1400px;
    }
    #mask{
      width: 100px;
      height: 100px;
      position: fixed;
      left: 50%;
      background: yellow;
      transform: translateX(-50%);
      display: none;
    }
  </style>
  <script>
    window.onload = function(){
       
      var haoroomsId = document.getElementById('haorooms');
      var MutationObserver = window.MutationObserver || window.webkitMutationObserver || window.MozMutationObserver;

      var recordHeight = 0;
      var mutationObserver = new MutationObserver(function (mutations) {
        console.log(mutations);
        //给iframe 设置高度
        top.window.callback()

      })

      mutationObserver.observe(haoroomsId, {
        childList: true, // 子节点的变动(新增、删除或者更改)
        attributes: true, // 属性的变动
        characterData: true, // 节点内容或节点文本的变动
        subtree: true // 是否将观察器应用于该节点的所有后代节点
      })

    }
    function showBox(){
      debugger
      let mask = document.getElementById('mask');
      mask.style.display="block"
      var topx = top.window.pageYOffset
      console.log(topx)
      mask.style.top=topx+"px"
      top.window.document.body.style.overflowY="hidden"

    }
    function closeBox(){
      let mask = document.getElementById('mask');
      mask.style.display="none"
      top.window.document.body.style.overflowY="auto"

    }
    var init=10
    function add(){
      debugger
      var bottom = document.getElementById('bottom')
      init=init+10
      bottom.style.height=init+'px'
    }
  </script>
</head>
<body id="haorooms">
  <div class="box">
    <button class="btn0" onclick="add()">btn100</button>

    <button class="btn" onclick="showBox()">btn0</button>

    <button class="btn1" onclick="showBox()">btn1</button>
    <button class="btn2" onclick="showBox()">btn2</button>

  </div>
  <div id="bottom"></div>
  <div id="mask">
    <button onclick="closeBox()">close</button>
  </div>
</body>
</html>

btn0,btn1,btn2 都是触发弹层展示的,在点击触发showBox的时候获取到当前滚动条的位置 ,然后给结应的弹层设置top 高度 ,这样就会随着滚动条的滚动正常的显示弹窗了。获取iframe 外层滚动条用top.window.pageYOffset 获取 ,当然这个对于高版本浏览器没有问题,为了使用兼容性 top.window.pageYOffset || top.window.document.body.scrollTop || top.window.document.documentElement.scrollTop