zoukankan      html  css  js  c++  java
  • 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`;
          });
    } }

     

        

  • 相关阅读:
    用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单
    用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象
    用 Flask 来写个轻博客 (18) — 使用工厂模式来生成应用对象
    用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目
    用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目
    Nginx详解八:Nginx基础篇之Nginx请求限制的配置语法与原理
    Nginx详解七:Nginx基础篇之Nginx官方模块
    Nginx详解六:Nginx基础篇之Nginx日志
    Nginx详解五:Nginx基础篇之HTTP请求
    Nginx详解四:Nginx基础篇之目录和配置语法
  • 原文地址:https://www.cnblogs.com/qianyou304/p/14155764.html
Copyright © 2011-2022 走看看