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