Vue中使用iframe踩坑問(wèn)題記錄 iframe+postMessage
使用iframe踩坑記錄 iframe+postMessage
需求:最近在寫(xiě)一個(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é)都不是很好,就自己直接寫(xiě)了。
在iframe的子頁(yè)面中:函數(shù)寫(xiě)在methods中,怎么去觸發(fā)getScrollHeight()這個(gè)函數(shù)看你具體的情況。注意一下,postMessage的源路徑,想要將信息傳遞到哪里。
為什么要寫(xiě)定時(shí)器?如果頁(yè)面內(nèi)容超多,高度值很大,像我的就到了2W多px,需要等到頁(yè)面加載完成后才能獲取滾動(dòng)高度,延時(shí)短了什么的是不能夠獲取準(zhǔn)確的高度值,會(huì)造成iframe的父級(jí)頁(yè)面出現(xiàn)雙滾動(dòng)條,影響體驗(yàn)。
最后,在頁(yè)面銷(xiāo)毀之前記得要清除定時(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); } })
寫(xiě)好之后記得刷新頁(yè)面,不然就會(huì)像我一樣明明已經(jīng)改好了但還是看不到數(shù)據(jù)。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue 進(jìn)階之實(shí)現(xiàn)父子組件間的傳值
這篇文章主要介紹了vue 進(jìn)階之實(shí)現(xiàn)父子組件間的傳值,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue3關(guān)鍵字高亮指令的實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了vue3實(shí)現(xiàn)關(guān)鍵字高亮指令的相關(guān)資料,w文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下2023-11-11vuejs element table 表格添加行,修改,單獨(dú)刪除行,批量刪除行操作
這篇文章主要介紹了vuejs element table 表格添加行,修改,單獨(dú)刪除行,批量刪除行操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07vue-cli的build的文件夾下沒(méi)有dev-server.js文件配置mock數(shù)據(jù)的方法
這篇文章主要介紹了vue-cli的build的文件夾下沒(méi)有dev-server.js文件配置mock數(shù)據(jù)的方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04vue2.0 + ele的循環(huán)表單及驗(yàn)證字段方法
今天小編就為大家分享一篇vue2.0 + ele的循環(huán)表單及驗(yàn)證字段方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09