一、问题描述
在使用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`; });
} }