Vue中使用iframe踩坑問(wèn)題記錄 iframe+postMessage
使用iframe踩坑記錄 iframe+postMessage
需求:最近在寫一個(gè)博客的功能模塊,技術(shù)棧是單獨(dú)選擇的vuepress,完成后想要融合到一個(gè)vue工程里,考慮到后期維護(hù)的問(wèn)題,就通過(guò)iframe將vuepress打包后的工程頁(yè)面引入到vue工程的一個(gè)頁(yè)面中,這樣iframe的父子級(jí)頁(yè)面之間也要進(jìn)行信息的傳遞,比如說(shuō)傳遞iframe的子頁(yè)面的滾動(dòng)高度給父頁(yè)面,然后撐開(kāi)頁(yè)面高度。
1.iframe的初始高度問(wèn)題
vue工程的一個(gè)組件,也就是iframe的父頁(yè)面,引入html;這里出現(xiàn)第一個(gè)坑,就是iframe的初始高度一定要設(shè)置,具體高度值可以預(yù)估一下iframe子頁(yè)面的高度,否則加載的時(shí)候就會(huì)出現(xiàn)閃屏的現(xiàn)象,體驗(yàn)不好;如果iframe的子頁(yè)面高度是變化的,也就是說(shuō)iframe要實(shí)現(xiàn)高度的自適應(yīng),接下往下看。。。
<div id="iframeBox"> ? ?<iframe id="iframeCon" src="./blog/index.html" width="100%" height="800px"></iframe> </div>
2.postMessage的實(shí)現(xiàn)
上面說(shuō)到iframe要實(shí)現(xiàn)高度自適應(yīng),就需要借助postMessage來(lái)實(shí)現(xiàn)了,自己之前沒(méi)用過(guò)這個(gè),找了很多資料說(shuō)的感覺(jué)都不是很好,就自己直接寫了。
在iframe的子頁(yè)面中:函數(shù)寫在methods中,怎么去觸發(fā)getScrollHeight()這個(gè)函數(shù)看你具體的情況。注意一下,postMessage的源路徑,想要將信息傳遞到哪里。
為什么要寫定時(shí)器?如果頁(yè)面內(nèi)容超多,高度值很大,像我的就到了2W多px,需要等到頁(yè)面加載完成后才能獲取滾動(dòng)高度,延時(shí)短了什么的是不能夠獲取準(zhǔn)確的高度值,會(huì)造成iframe的父級(jí)頁(yè)面出現(xiàn)雙滾動(dòng)條,影響體驗(yàn)。
最后,在頁(yè)面銷毀之前記得要清除定時(shí)器。個(gè)人感覺(jué)如果只有一個(gè)定時(shí)器,或者這個(gè)setTimeout不是為了實(shí)現(xiàn)setInterval的效果,也沒(méi)有其他的摻雜,是不用清除的。
beforeDestroy() {
? ?clearTimeout(this.timer);
},
?
methods: {
? ? getScrollHeight() {
? ? ? ?this.timer = setTimeout(() => {
? ? ? ? ?et height = document.body.scrollHeight;
? ? ? ? ? window.parent.postMessage(height, "/");
? ? ? ?}, 100);
? ? }
}在iframe的父級(jí)頁(yè)面中如何接收信息呢? 這里采用事件的監(jiān)聽(tīng),每次有子頁(yè)面?zhèn)鬟f信息的出現(xiàn),我們就獲取到傳遞信息中的高度值,然后設(shè)置給當(dāng)前頁(yè)面。同樣的記得移除監(jiān)聽(tīng)。
created () {
? window.addEventListener('message', this.setHeightUpdate, false)
},
destroyed () {
? window.removeEventListener('message', this.setHeightUpdate, false)
},
methods: {
? setHeightUpdate () {
? ? let iframe = document.getElementById('iframeCon')
? ? iframe.height = event.data + 100 // 這里的event就是子頁(yè)面?zhèn)鬟^(guò)來(lái)的信息,可以打印到控制臺(tái)看
? ? window.scrollTo(0, 0) // 為了回到頂部
? }
}我遇到的就是這些了,雖然簡(jiǎn)單,但是知識(shí)呀。。。
iframe使用postMessage傳值addEventListener未接收到卻收到webpackwarning問(wèn)題
項(xiàng)目中使用到iframe,iframe跨域通信需要使用postMessage發(fā)送消息,addEventListener接收消息。
原先是獲取當(dāng)前窗口的數(shù)據(jù)發(fā)送過(guò)去。
const _iframe = document.getElementById('iframeViewer').contentWindow
let _obj = res.data.data
_obj.type = 'view'
_obj.currentProcessInstanceId = row.id
let Base64 = require('js-base64').Base64
_obj.processXml = Base64.decode(res.data.data.processXml)
_iframe.postMessage(JSON.stringify(_obj), '*')后來(lái)項(xiàng)目需求更新,需要將本來(lái)的窗口多加幾個(gè)菜單,可以進(jìn)行頁(yè)面切換。加了新的菜單之后就出現(xiàn)了問(wèn)題,postMessage發(fā)送出了消息,控制臺(tái)打印出來(lái)addEventListener接收到的消息變成了webpack相關(guān)。
bug如下

問(wèn)了大哥,發(fā)現(xiàn)問(wèn)題可能是因?yàn)閣ebpack自身會(huì)發(fā)送postMessage,需要區(qū)分接收到的是webpack發(fā)的還是自己發(fā)的。另外iframe是動(dòng)態(tài)生成的,未加載好就發(fā)送postMessage,webpack會(huì)幫助發(fā)送。(大概是因?yàn)檫@個(gè),具體的不清楚)
問(wèn)題解決
所以一個(gè)是需要在iframe加載好之后發(fā)送postMessage,另一個(gè)是區(qū)分接收到的是webpack發(fā)的還是自己發(fā)的。
定義 const _iframe = document.getElementById('iframeViewer').contentWindow 獲取目標(biāo)窗口的窗口對(duì)象
定義iframeViewer = document.getElementById('iframeViewer') 獲取iframe元素對(duì)象
然后使用onload事件,window.οnlοad=function(){SomeJavaScriptCode};(onload事件會(huì)在頁(yè)面或圖像加載完成后立即發(fā)生)
const _iframe = document.getElementById('iframeViewer').contentWindow
const iframeViewer = document.getElementById('iframeViewer')
let _obj = res.data.data
_obj.type = 'view'
_obj.currentProcessInstanceId = this.currentProcessInstanceId
let Base64 = require('js-base64').Base64 _obj.processXml = Base64.decode(res.data.data.processXml)
iframeViewer.onload = () => {
console.log('iframeViewer已加載')
_iframe.postMessage(JSON.stringify(_obj), '*')
}這樣就確保了在iframe加載后再發(fā)送postMessage。
在addEventListener接收時(shí),因?yàn)閜ostMessage發(fā)送的時(shí)候傳了一個(gè)type,所以可以通過(guò)type來(lái)判斷發(fā)過(guò)來(lái)的是哪個(gè)event。
window.addEventListener("message", function(event) {
_this.parentData = event.data;
if (JSON.parse(_this.parentData).type === "view") {
_this.frontTask = JSON.parse(_this.parentData).frontTask;
_this.currentTask = JSON.parse(_this.parentData).currentTask;
_this.backTask = JSON.parse(_this.parentData).backTask;
_this.historyTask = JSON.parse(_this.parentData).historyTask;
_this.processInstanceId = JSON.parse(_this.parentData).currentProcessInstanceId;
_this.createNewDiagram(JSON.parse(_this.parentData).processXml);
}
})寫好之后記得刷新頁(yè)面,不然就會(huì)像我一樣明明已經(jīng)改好了但還是看不到數(shù)據(jù)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue3實(shí)現(xiàn)el-table分批渲染表格
這篇文章主要為大家詳細(xì)介紹了vue3項(xiàng)目中如何實(shí)現(xiàn)el-table分批渲染表格,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
vue移動(dòng)端微信授權(quán)登錄插件封裝的實(shí)例
今天小編就為大家分享一篇vue移動(dòng)端微信授權(quán)登錄插件封裝的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
詳解Vue的數(shù)據(jù)及事件綁定和filter過(guò)濾器
這篇文章主要為大家介紹了Vue的數(shù)據(jù)及事件綁定和filter過(guò)濾器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-01-01
Vue.js開(kāi)發(fā)環(huán)境快速搭建教程
這篇文章主要為大家詳細(xì)介紹了Vue.js開(kāi)發(fā)環(huán)境快速搭建教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
uniapp中如何基于vue3實(shí)現(xiàn)輸入驗(yàn)證碼功能
本文介紹了如何使用uniapp和vue3創(chuàng)建一個(gè)手機(jī)驗(yàn)證碼輸入框組件,通過(guò)封裝VerificationCodeInput.vue組件,并在父組件中引入,可以實(shí)現(xiàn)驗(yàn)證碼輸入功能,適合需要增加手機(jī)驗(yàn)證碼驗(yàn)證功能的開(kāi)發(fā)者參考使用2024-09-09
vue動(dòng)態(tài)子組件的兩種實(shí)現(xiàn)方式
這篇文章主要介紹了vue動(dòng)態(tài)子組件的兩種實(shí)現(xiàn)方式,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
webpack+vue+express(hot)熱啟動(dòng)調(diào)試簡(jiǎn)單配置方法
今天小編就為大家分享一篇webpack+vue + express (hot) 熱啟動(dòng)調(diào)試簡(jiǎn)單配置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09

