之所以调研iframe技术,是因为一个问题引起的。
问题:主项目通过iframe嵌套子项目,子项目弹框无法全屏,请问有什么方案解决呢?
经过调研,有以下方式解决:
- 主项目实现一个弹框,子项目和主项目进行通信,对弹框进行控制。
- 子项目通过getContainer把弹框挂载到主项目的body上。
- 如果是简单的弹框,可以手写一个。
第1种方案是比较通用的方案,比较简单。
但有时候会存在这样的问题,主项目无法修改,怎么办?只能用第3种方案,自己手写一个弹框了。
好多人会使用第2中方案,因为毕竟a-modal给出了这样的api,但第2种方案有坑,并且坑不小。它不是一个通用方案不建议使用,实在没办法,也可以尝试着一用。
第2种方案会存在以下问题:
- 子项目挂载到主项目的body上,a-modal的样式丢失。
以上问题如何解决:
第一种方法:在主项目上放一个a-modal,用v-show="false"隐藏,这样子项目挂载到主项目body上的a-modal也有了样式。
主项目
xml
<template>
<a-card title="主项目 - 子项目展示">
<div>
<iframe
ref="iframeRef"
:src="subAppUrl"
frameborder="0"
></iframe>
</div>
<!-- 可以用v-show -->
<a-modal v-show="false" v-model:open="open" title="Basic Modal" @ok="handleOk">
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</a-modal>
</a-card>
</template>
<script setup>
import { ref } from 'vue'
const iframeRef = ref(null)
// 通过代理访问子项目,确保同域名
const subAppUrl = ref('/sub-app/')
const open = ref(true);
const showModal = () => {
open.value = true;
};
const handleOk = (e) => {
console.log(e);
open.value = false;
};
</script>
ini
<script setup>
import { ref } from 'vue'
const iframeRef = ref(null)
// 通过代理访问子项目,确保同域名
const subAppUrl = ref('/sub-app/')
const open = ref(true);
const showModal = () => {
open.value = true;
};
const handleOk = (e) => {
console.log(e);
open.value = false;
};
</script>
子项目
ini
<a-modal
v-model:open="modalVisible"
title="弹框"
width="600px"
:get-container="getContainer"
@ok="handleOk"
@cancel="handleCancel"
>
<div class="modal-content">
<h2>这是一个弹框</h2>
<p>弹框内容区域</p>
<a-space>
<a-button>按钮1</a-button>
<a-button>按钮2</a-button>
</a-space>
</div>
</a-modal>
javascript
// 获取主项目的body作为弹框容器
const getContainer = () => {
try {
// 通过 window.parent 访问主项目的 document
if (window.parent && window.parent !== window.self) {
console.log('window.parent.document:', window.parent.document)
if (window.parent.document && window.parent.document.body) {
console.log('成功获取父窗口body')
return window.parent.document.body
}
} else {
console.warn('window.parent 不存在或等于 window.self')
}
} catch (e) {
// 如果跨域,会抛出错误,则使用当前窗口的body
console.error('无法访问父窗口,使用当前窗口body:', e)
}
console.log('使用当前窗口body')
return document.body
}
第二种方式:需要把a-modal的样式注入进去。
这种代码就不贴了,个人觉得比较麻烦,并且还有不确定的边界,个人不建议用这种方式。