跨域 iframe 隱藏頁面元素,高度自適應


技術棧

系統 A 和系統 B 均使用 vue2 

 

需求

A 中嵌入 B 系統頁面,兩種情況

1、去掉頁面 header、footer,僅保留頁面主體

2、保留 header,去掉 footer、header 中 logo、用戶信息

禁用 iframe 中滾動,iframe 窗體高度與 B 中頁面一致,使用瀏覽器滾動條

 

1 隱藏元素

方案制定

域名不同存在跨域,無法在 A 中直接操作 B 中元素,需 B 系統開發者提供支持

iframe 加載之后,給 B 發送消息,B 接收到后將元素隱藏

實現

A 系統,展示 iframe 的 vue 文件

 1 <template lang="pug">
 2 .iframe-box
 3     iframe(id="iframeInstance" name="iframeInstance" src="http://localhost:8008" scrolling="auto" frameborder="no" seamless ref="iframe" width="100%" height="600")
 4 </template>
 5 
 6 <script>
 7 export default {
 8     async mounted() {
 9         await this.$nextTick()
10         this.$refs.iframe.addEventListener('load', this.onIframeLoad) // 給 iframe 綁定監聽事件
11     },
12 
13     methods: {
14         onIframeLoad() {
15             console.log('onload')
16             this.$refs.iframe.contentWindow.postMessage({ header: false }, '*') // 加載完成之后發送消息,已知目標地址時不要用*,這里的 false 和 true 對應上述需求中兩種情況
17         }
18     },
19 }
20 </script>

 

B 系統,App.vue

 1 mounted () {
 2     window.addEventListener('message', (event) => {
 3         // 判斷消息來源
 4         const arr = ['xxx.com', 'xxxx.com', 'xxx.cn']
 5         const flag = arr.some(item => event.origin.includes(item))
 6         if (!flag) return
 7 
 8         console.log('message', event.data)
 9 
10         // 如果兩個系統不是單點登錄同步登錄信息,可以接收用戶信息后登錄
11         if (this.$store.getters.unLogin) {
12             // login
13         }
14 
15         // 隱藏 footer
16         const footer = document.querySelector('#app .footer')
17         footer.style.display = 'none'
18 
19         // 根據接收的消息隱藏對應元素
20         if (event.data.header) {
21             const logo = document.querySelector('#app .header .logo')
22             const user = document.querySelector('#app .header .user-info')
23             logo.style.display = 'none'
24             user.style.display = 'none'
25         } else {
26             const header = document.querySelector('#app .header')
27             header.style.display = 'none'
28         }
29     }, false);
30 }

 

2 高度自適應

方案

受跨域限制,B 提供高度,A 接收后調整 iframe height 屬性

考慮到展示內容可能收到 tab 切換和過濾條件等影響,通過路由守衛發送消息不滿足需求,采用 MutationObserver,監聽根元素和子元素

實現

A系統,iframe 展示的 vue 文件

 1 <template lang="pug">
 2 .i-iframe
 3     iframe(id="iframeInstance" name="iframeInstance" src="http://localhost:8008" scrolling="no" frameborder="no" seamless ref="iframe" width="100%" :height="height")
 4 </template>
 5 
 6 <script>
 7     export default {
 8         data() {
 9             return {
10  height: 600, 11             }
12         },
13 
14         async mounted() {
15             await this.$nextTick()
16             this.$refs.iframe.addEventListener('load', this.onIframeLoad)
17         },
18 
19         created() {
20  window.addEventListener('message', event => { 21  const height = event.data.height || 800
22                 if(this.height === height) return
23                 this.height = height 24  }, false) 25         },
26 
27         methods: {
28             onIframeLoad() {
29                 console.log('onload')
30                 this.$refs.iframe.contentWindow.postMessage({ header: true }, '*')
31             },
32         },
33     }
34 </script>

 

B 系統,App.vue

 1 mounted () {
 2     // 可以寫成個方法放 methods 里,這里為了方便展示執行時機就不改了
 3     const targetNode = document.getElementById('app');
 4     const config = { attributes: false, childList: true, subtree: true };
 5     
 6     // 加防抖,避免多次觸發
 7     const callback = debounce(() => {
 8         // B 系統設置了 min-height: 100%,過濾條件變化,數據量減少時,由於展示空間足夠,高度仍保持上一次的,在這里做一次初始化
 9         window.parent.postMessage({ height: undefined }, '*'); 10 
11         // 渲染完成后提供最新的頁面高度
12         setTimeout(() => { 13             window.parent.postMessage({ height: targetNode.offsetHeight }, '*'); 14         }, 70); 15     }, 300)
16 
17     const Mutation =
18         window.MutationObserver ||
19         window.WebKitMutationObserver ||
20         window.MozMutationObserver;
21     this.observer = new Mutation(callback);
22     this.observer.observe(targetNode, config);
23 },
24 
25 beforeDestroy () {
26     if(this.observer) {
27       this.observer.disconnect()
28       this.observer = null
29     }
30 }

 

補充

此需求中 A、B 兩系統使用單點登錄,自動同步登錄信息。如有同步登錄態信息需求,可參考隱藏元素實現代碼

A 傳遞消息時,增加用戶信息。B 接收后執行登錄操作

B 系統登出時,傳遞消息給 A 系統,A 決定跳轉登錄頁或其他操作

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM