背景:
因为领导决策,将 A 系统复制出一份代码改头换面变成 B 系统,并要求在 B 系统开发一个模块给供应商使用,开发完了,好的,现在领导又想要把这个页面搬到 A 系统给公司内部工程师使用了。。。。。。
矛盾点:
-
如果直接将文件复制过来用,以后每次更新都要两边改,维护特别困难;
-
如果把这个页面单独封装成一个大的组件去复用,工作量更加是无敌庞大。
遂:直接 iframe 嵌入
这样做可以实现只在一个地方维护该模块,大大减少工作量。
前提是:
已经再三确认,以后 A、B 系统中的这个页面是一致的,不会进行差异化定制;
各项细小的操作权限和 B 系统中的保持一致,直接在后台中对B系统的权限规则进行勾选
问题:
-
测试服和正式服的页面地址不同;
-
页面存在顶部和侧面菜单栏
解决:
- 在 A 系统中新增一个路由,指向一个放着 iframe 的Vue文件;
html
<template>
<div class="chat-container">
<iframe
:src="src"
frameborder="0"
width="100%"
height="100%"
id="myiframe"
sandbox="allow-scripts allow-same-origin allow-forms"
@load="handleIframeLoad"
/>
</div>
</template>
<script>
export default {
name: 'FQATest',
components: {},
props: {},
data() {
return {}
},
computed: {
src() {
// 尝试添加参数来跳过有问题的认证流程
const baseUrl = process.env.NODE_ENV === 'production'
? '正式服页面地址'
: '测试服页面地址'
return `${baseUrl}?skipAuth=true&bypassTokenCheck=true`
}
},
created() {},
mounted() {
},
methods: {
handleIframeLoad() {
// 添加错误捕获
const iframe = document.getElementById('myiframe')
iframe.contentWindow.onerror = function(msg, url, line) {
console.log('iframe错误:', msg, url, line)
return true // 阻止错误冒泡
}
}
}
}
</script>
<style lang="scss" scoped>
.chat-container {
height: calc(100vh - 85px);
}
</style>
- 在 B 系统中的 Layout 布局组件中进行环境判断,如果是在 iframe 嵌套环境下,那么只显示主内容,否则正常显示(有顶部和侧边菜单栏)。
核心代码:
html
<template>
<div>
<!-- 系统内部 -->
<div :class="classObj" class="app-wrapper" v-if="!iframeEmbedded">
<div
v-if="device === 'mobile' && sidebar.opened"
class="drawer-bg"
@click="handleClickOutside"
/>
<sidebar class="sidebar-container" />
<div class="main-container">
<div v-if="showHeader" :class="{ 'fixed-header': fixedHeader }">
<navbar />
<tags-view v-if="needTagsView" />
</div>
<app-main />
</div>
</div>
<!-- 被嵌入iframe -->
<div v-else>
<app-main />
</div>
</div>
</template>
逻辑判断:
javascript
data() {
return {
iframeEmbedded: false // 是否被iframe嵌入
}
},
mounted() {
this.checkIframeEmbedded()
},
methods: {
// 检测是否被iframe嵌入
checkIframeEmbedded() {
try {
// 方法1: 检查window.self和window.top是否相同
if (window.self !== window.top) {
this.iframeEmbedded = true
console.log('✅ 检测到iframe嵌入: window.self !== window.top',this.iframeEmbedded)
return true
}
// 方法2: 检查window.frameElement是否存在
if (window.frameElement) {
this.iframeEmbedded = true
console.log('✅ 检测到iframe嵌入: window.frameElement存在',this.iframeEmbedded)
return true
}
// 方法3: 检查URL参数中是否包含iframe标识
const urlParams = new URLSearchParams(window.location.search)
if (urlParams.has('iframe') || urlParams.has('embedded')) {
this.iframeEmbedded = true
console.log('✅ 检测到iframe嵌入: URL参数包含iframe标识',this.iframeEmbedded)
return true
}
// 方法4: 检查referrer是否来自同一域名(可选)
if (document.referrer && document.referrer !== '' &&
document.referrer !== window.location.href) {
// 如果referrer存在且不是当前页面,可能是被嵌入
const currentDomain = window.location.hostname
const referrerDomain = new URL(document.referrer).hostname
if (referrerDomain !== currentDomain) {
this.iframeEmbedded = true
console.log('✅ 检测到iframe嵌入: referrer来自不同域名',this.iframeEmbedded)
return true
}
}
this.iframeEmbedded = false
console.log('❌ 未检测到iframe嵌入',this.iframeEmbedded)
return false
} catch (error) {
// 如果出现跨域错误,说明被iframe嵌入
console.log('iframe检测出现错误,可能被嵌入:', error)
this.iframeEmbedded = true
return true
}
},
}
这样就大功告成啦!以后只需要在 B 系统中维护该模块即可,A 系统这边也会同步更新。

