vue+ElementUI下iframe子页面弹窗蒙层遮罩问题优化

一、问题描述

    在使用iframe时,子页面的弹框遮罩只能覆盖子页面,而无法扩展到父页面。(如下图)

    

二、解决方案 

    0、前提:弹出的内容高度和宽度不能超过子页面的范围(否则会出现滚动条)

    1、父页面:

    当子页面需要弹框时,父页面也弹出空弹框,使得整个页面能够遮罩,然后将子页面的层级提高,使子页面可以由子页面自己控制。监听子页面发来的遮罩处理信号,如果是true,则将iframe的position变成absolute,zIndex设为较大的值10000;隐藏滚动条;弹出空的弹窗(设置点击空白、按Esc键无法取消)。如果是false,则将position设为unset;关闭弹窗。

    (1)父页面HTML

<template>
  <div class="parent" id="parentDiv">
    <template>
      <iframe
        ref="iframe"
        id="bdIframe"
        :src="src"
        width="100%"
        height="auto"
        scrolling="no"
        frameborder="0"
      ></iframe>
    </template>
    <el-dialog
      :visible.sync="dialogTableVisible"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
    ></el-dialog>
  </div>
</template>

       (2)父页面监听子页面处理弹框消息的JS

changeDialog(data) {
      //isDialog为子页面弹框的开关
      this.dialogTableVisible = data.isDialog;
      if (data.isDialog) {
        //当子页面弹框开时
        //父页面外部滚动条隐藏
        document.getElementsByClassName("indexCon")[0].style.overflow = "hidden";
        //将子页面iframe页面层级提升
        document.getElementById("parentDiv").style.position = "relative";
        document.getElementById("bdIframe").style.position = "absolute";
        document.getElementById("bdIframe").style.zIndex = 10000;
      } else {
        //当子页面弹框关时
        //恢复
        document.getElementsByClassName("indexCon")[0].style.overflow = "auto";
        document.getElementById("parentDiv").style.position = "unset";
        document.getElementById("bdIframe").style.position = "unset";
        document.getElementById("bdIframe").style.zIndex = "unset";
      }
    },

附上父页面的滚动条监听方法,在页面较长时,需要修改子页面的弹窗位置。

(3)父页面抛出滚动条监听

    sendMassage(data) {
      let bdIframe = document.getElementById("bdIframe");
      if (bdIframe) {
        let mapFrame = bdIframe.contentWindow;
        this.$nextTick(() => {
          mapFrame.postMessage(
            {
              handlerType: "getScrollHeight",
              params: {
                height: data.height,
              },
            },
            "*"
          );
        });
      }
    },

(4)父页面监听滚动条距离顶部的距离方法,在项目最外层的index.vue中设置

getScroll (event) {
      this.$nextTick(() => {
        top.postMessage(
          {
            handlerType: "sendMassage",
            params: {
              height: event.target.scrollTop,
            },
          },
          "*"
        );
      });
      this.$refs.oIndexR.style.top = `${event.target.scrollTop}px`;
    },

    2、子页面

    如果页面高度有大于一页高度的情况存在,需要先监听主站的滚动条距离顶部的位置。
    点击弹框,弹出弹框(设置点击空白、按Esc键无法取消、有关闭按钮的需要设置before-close关闭弹框),如果存在情况1,还需要设置margin-top或者top的值为主站的滚动条距离。
    根据弹框弹出或者关闭的visible的值,想主站发送当前的visible,做到同步开关。

    (1)子页面el-dialog弹框HTML,messageBox弹框同理

<el-dialog
        :visible.sync="dialogTableVisible"
        center
        :modal-append-to-body="false"
        :close-on-press-escape="false"
        :close-on-click-modal="false"
      >
</el-dialog>

    (2)触发关闭或者打开弹框的JS

      this.dialogTableVisible = false;//关闭false,打开true
      dialogPostMessage(false);
dialogPostMessage(isDialog) {
    top.postMessage(
        {
            handlerType: "changeDialog",
            params: {
                isDialog: isDialog,
            },
        },
        "*"
    );
}

   

    (3)附上需要监听滚动条情况

data(){
    return{
       //当前滚动条距离顶部高度
       scrollHeight: 0
    }
}

created() {
    //监听主页面postmessage
    window.addEventListener(
      "message",
      (event) => {
        const { data } = event;
        this[data.handlerType] && this[data.handlerType](data.params);
      },
      false
    );
  },
beforeDestroy() {
    window.removeEventListener(
      "message",
      (event) => {
        const { data } = event;
        this[data.handlerType] && this[data.handlerType](data.params);
      },
      false
    );
},
methods:{
    //监听滚动条高度
    getScrollHeight(data) {
      this.scrollHeight = data.height;
    },      
    showDialog(){      
     dialogPostMessage(true);
      this.dialogTableVisible = true;
      ......
      //预览弹框位置调整
      let elDialogs = document.getElementsByClassName("el-dialog");
      elDialogs.forEach((elDialog) => {
          elDialog.style.marginTop = `${this.scrollHeight}px`;
      });
} }

 

    

原文地址:https://www.cnblogs.com/qianyou304/p/14155764.html