vue中iframe使用以及結(jié)合postMessage實現(xiàn)跨域通信
使用場景
需求
在一個H5項目的頁面中以url的方式嵌入另一個項目的頁面。(不得不使用iframe)
而為了兼容移動端api(封裝的一個移動端api,iframe內(nèi)嵌頁面不生效),需要實現(xiàn)父子頁面的通信 (使用postMessage)。
iframe使用
基本使用
直接在頁面嵌套iframe標(biāo)簽指定src即可使用iframe。
<iframe src="xxx.html"></iframe>
常用屬性
frameborder:是否顯示邊框,1(yes),0(no)height:框架作為一個普通元素的高度。width:框架作為一個普通元素的寬度。name:框架的名稱,window.frames[name]時專用的屬性。scrolling:框架的是否滾動。yes,no,auto。src:內(nèi)框架的地址,可以使頁面地址,也可以是圖片的地址。sandbox:對iframe進行一些列限制,IE10+支持
更多屬性訪問: 這里
iframe高度自適應(yīng)
let ifr = document.getElementById('ifr')
const deviceHeight = document.documentElement.clientHeight;
ifr.style.height = (Number(deviceHeight)) + 'px';?vue中需要在mounted()中進行高度初始化
獲取iframe的內(nèi)容
通過兩個主要的API:contentWindow 和 contentDocument
iframe.contentWindow,獲取iframe的window對象iframe.contentDocument,獲取iframe的document對象
var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window",iwindow);?? ?//獲取iframe的window對象
console.log("document",idoc);?? ?//獲取iframe的document
console.log("html",idoc.documentElement);?? ?//獲取iframe的html
console.log("head",idoc.head);?? ?//獲取head
console.log("body",idoc.body);?? ?//獲取body通過Name屬性,通過window提供的frames獲取
<iframe src ="xxx.html" id="ifr1" name="ifr1" scrolling="yes">
? ? <p>Your browser does not support iframes.</p>
</iframe>
<script type="text/javascript">
? ? console.log(window.frames['ifr1'].window);
? ? console.dir(document.getElementById("ifr1").contentWindow);
</script>window.frames['ifr1'] 返回的就是window對象,即 window.frames['ifr1']===window
同域下獲取父級/子級內(nèi)容
window.parent:獲取上一級的window對象,如果還是iframe則是該iframe的window對象window.top:獲取最頂級容器的window對象
iframe跨域
以下形式的跨域,可以使用iframe進行解決。某一方使用iframe嵌套在另一方。
比如:http://www.foo.com/a.html 和 http://script.foo.com/b.html
兩個文件中分別加上 document.domain = 'foo.com',指定相同的主域,然后,兩個文檔就可以進行交互。
//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.foo.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
? ? var doc = ifr.contentDocument || ifr.contentWindow.document;
? ? // 在這里操縱b.html
? ? alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.foo.com上的b.html
document.domain = 'foo.com';默認情況下 document.domain 是指 window.location.hostname ??梢允謩痈模亲疃嘀荒茉O(shè)置為主域名。 通常,主域名就是指不帶www的hostname, 比如: foo.com , baidu.com 。
如果,帶上www或者其他的前綴,就是二級域名或者多級域名。通過上述設(shè)置,相同的domain之后,就可以進行同域的相關(guān)操作。
如果設(shè)置的iframe的域名和 top.window 的域名完全不同。則可以使用postMessage()進行通信
postMessage通信
window.postMessage() 方法可以安全地實現(xiàn)跨源通信。通常,對于兩個不同頁面的腳本,只有當(dāng)執(zhí)行它們的頁面位于具有相同的協(xié)議(通常為https),端口號(443為https的默認值),以及主機 (兩個頁面的模數(shù) Document.domain設(shè)置為相同的值) 時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規(guī)避此限制,只要正確的使用,這種方法就很安全。
具體使用方式參考:window.postMessage
<iframe src="http://xxx.com" name="sendMessage"></iframe>
父頁面向子頁面?zhèn)鬟f信息:
// 父頁面js
let ifr = window.frames['sendMessage'];
// 向子頁面發(fā)送message
ifr.postmessage('give u a message', "http://xxx.com");
// xxx.com頁面js
// 監(jiān)聽父頁面?zhèn)鱽淼男畔?
window.addEventListener('message', receiver, false);
function receiver(e) {
? ? if (e.origin == 'http://xxx.com') {
? ? ? ? if (e.data == 'give u a message') {
? ? ? ? ? ? e.source.postMessage('received', e.origin); ?// 向原網(wǎng)頁返回信息
? ? ? ? } else {
? ? ? ? ? ? alert(e.data);
? ? ? ? }
? ? }
}在vue中使用
<iframe :src="src" ref="iframe" frameborder="0"></iframe>
1.要將獲取到iframe的contentWindow屬性放到mounted這個鉤子函數(shù)中。
mounted() {
? ? this.iframeWin = this.$refs.iframe.contentWindow;
}2.子頁面向父頁面?zhèn)髦?/p>
父頁面代碼:
// 父頁面監(jiān)聽子頁面?zhèn)鱽淼男畔?
mounted() {
? ? window.addEventListener('message', this.handleMessage);
? ? this.iframeWin = this.$refs.iframe.contentWindow;
},
methods: {
? ? handleMessage (event) {
? ? ? ? const data = event.data.data
? ? ? ? if(data.info === "success"){
? ? ? ? ? ? alert(data.data)
? ? ? ? }
? ? }
}子頁面代碼:
sendMessage() {
? ? // 向父頁面發(fā)送信息
? ? window.parent.postMessage({
? ? ? ? data: {
? ? ? ? ? ? info:"success",
? ? ? ? ? ? data:"我是子頁面的test!"
? ? ? ? }
? ? }, '*');
}
3.父頁面向子頁面?zhèn)鬟f信息同理
sendMessage () {
? ? // 向子頁面?zhèn)鲾?shù)據(jù),需要注意這里沒有parent
? ? this.iframeWin.postMessage({
? ? ? ? info: 'success',
? ? ? ? data: "我是來自父頁面的data!"
? ? }, '*')
}注意父向子傳遞信息的時候,要等子頁面加載完成后,再進行通信
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue3中reactive和ref的實現(xiàn)與區(qū)別詳解
reactive和ref都是vue3實現(xiàn)響應(yīng)式系統(tǒng)的api,他們是如何實現(xiàn)響應(yīng)式的呢,reactive和ref又有什么區(qū)別呢,下面小編就來和大家詳細講講,希望對大家有所幫助2023-10-10
解決vue路由發(fā)生了跳轉(zhuǎn)但是界面沒有任何反應(yīng)問題
這篇文章主要介紹了解決vue路由發(fā)生了跳轉(zhuǎn)但是界面沒有任何反應(yīng)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
vue項目npm?run?build打包dist文件及打包后空白解決辦法
npm run build 這個命令會執(zhí)行Vue CLI中預(yù)定義的打包配置,并將打包后的文件存放在"dist"文件夾中,這篇文章主要給大家介紹了關(guān)于vue項目npm?run?build打包dist文件及打包后空白的解決辦法,需要的朋友可以參考下2023-10-10

