如何實(shí)現(xiàn)iframe父子傳參通信
在最近的項(xiàng)目里面,用到了不少關(guān)于iframe父子傳參通信的相關(guān)操作,記錄一下,雖然很簡單,但是確實(shí)十分有用的;
iframe通信可以分為2種,跨域和非跨域兩種.分別說明;
有一點(diǎn)很重要,iframe是可以給name 屬性的;給上name 屬性可以省下一些代碼;
非跨域 父調(diào)子
//父頁面 <button class="b" id="b">點(diǎn)擊</button> <iframe src="a.html" name='child' id="f"></iframe> <script> var ob=document.getElementById('b'); var msg='hellow,i'm your father!!' ob.onclick=function(){ if(child.document.readyState=="complete"){ child.window.fnChild(msg); //關(guān)鍵 } } </script> //子頁面 <script> function fnChild (arg) { console.log(arg); //確實(shí)得到了 hellow,i'm your father!! } </script>
父頁面調(diào)用子頁面使用 childFrameName.window.fnName();;當(dāng)然有一點(diǎn)很重要,你需要判斷iframe 里面的東西是否加載完成,如果加載未完成就調(diào)用的話是會(huì)報(bào)錯(cuò)的;
判斷iframe 加載是否完成有2種方法
1,childFrameName.document.readyState=="complete"來判斷;
2,childFrameName.onload=function(){} 使用onload 回調(diào)函數(shù),把調(diào)用的方法都寫在這個(gè)回調(diào)函數(shù)里面;
非跨域 子調(diào)父
//在父頁面 <div id="a" class="a"></div> <iframe src="a.html" name='child' id="f"></iframe> <script> function changeColor(){ var oDiv=document.getElementById('a'); oDiv.style.backgroundColor="red"; } </script> //在子頁面 <button class="ob" onclick="c()">anniu</button> <script> function c(){ parent.window.changeColor(); //關(guān)鍵 } </script>
同樣的,在子頁面調(diào)用父頁面的方法使用 parent.window.fnName()就可以了;
這種操作難免會(huì)遇到父頁面獲取子頁面的元素,或者子頁面獲取父頁面的元素進(jìn)行操作;
非跨域 父頁面獲取子頁面元素操作
首先,我們有幾種方法拿到子頁面的window對象或者doucument 對象,(還是使用上面的html)
//原生js 獲取子頁面window對象 1, var childWindow=document.getElementById("f").contentWindow; 2, var childWindow=document.getElementsByTagName('f')[0].contentWindow; //其實(shí)也就是普通的獲取方法,只是后面多了一個(gè)contentWindow; //jquery var childWindow=$('#f').contentWindow; //獲取子頁面的document對象 (假設(shè)已經(jīng)通過上面的方法得到了window對象) var frameDoc=childWindow.document; var frameBody=frameDoc.body; //jquery 也是跟上面的一樣 var frameDoc=$(childWindow.document); //原生獲取元素 childWindow.document.getElementById('a') //上面都已經(jīng)拿到了子頁面的window對象,所以獲取子頁面的元素也就只需要想普通操作那樣獲取就好 childWindow.document.getElementById('a').style.color='red' //改個(gè)顏色 //jq拿子頁面元素 $('#f').contents().find('#a'); //$('#f').contents 這相當(dāng)于拿到了iframe 里面所有的dom;
非跨域 子頁面獲取父頁面元素
//原生js window.parent.document.getElementById('a'); //window.parent獲取到父頁面的window對象,那么接可以使用一般操作獲取元素 window.parent.document.getElementById('a').style.color="red";//dom操作 //jquery $("#a",parent.document); //$(父頁面元素選擇器, parent.document); $("#a",parent.document).css('border','1px solid red');
上面的是不存在跨域的情況,但是有時(shí)候會(huì)遇到跨域情況,在這次的項(xiàng)目里面就是出于跨域狀態(tài)下,開始看了一些資料,說是在用一個(gè)iframe做中間層去做,但是太麻煩,在這里介紹一個(gè)十分還用的方法postMessage
postMessage
window.postMessage() 方法可以安全地實(shí)現(xiàn)跨源通信。通常,對于兩個(gè)不同頁面的腳本,只有當(dāng)執(zhí)行它們的頁面位于具有相同的協(xié)議(通常為https),端口號(443為https的默認(rèn)值),以及主機(jī) (兩個(gè)頁面的模數(shù) Document.domain設(shè)置為相同的值) 時(shí),這兩個(gè)腳本才能相互通信。window.postMessage() 方法提供了一種受控機(jī)制來規(guī)避此限制,只要正確的使用,這種方法就很安全。
以上摘自MDN 原文 postMessage;
otherWindow.postMessage(message, targetOrigin, [transfer]); //otherWindow 窗口對象 // message 傳遞的消息,可以是對象,可以是字符串 // target 目標(biāo)窗口,* 代表所有;
postMessage十分強(qiáng)大,既可以子傳父,也可以父穿子,并且可以突破同源限制
來看我遇到的使用場景;
我在主頁面有個(gè)透明遮罩,里面是一個(gè)iframe的登錄窗口,在子頁面點(diǎn)擊關(guān)閉的時(shí)候,需要關(guān)掉父頁面的這個(gè)登陸遮罩;在這里存在跨域,所以使用上面的獲取元素,操作元素的方法不能夠使用,這里使用postMassage來做
//子頁面 <div id="loginBox">登錄窗口</div> <div id="close"></div> //父頁面 <div id="loginMask"> <iframe src="子頁面"></iframe> </div> //子頁面 <script> let oClose=document.getElementById('#close'); oClose.onclick=function(){ window.parent.postMessage('close','*'); } </script> //父頁面 <script> window.addEventListener('message',function(event){ if(event.data=='close'){ let oLoginMask=document.getElementById('loginMask'); oLoginMask.style.display="none"; } }) </script>
上面的代碼其實(shí)很簡單,在子頁面里面獲取了元素,該元素觸發(fā)點(diǎn)擊事件的時(shí)候,向父窗口發(fā)送一個(gè)消息,傳遞了一個(gè)消息;(這個(gè)消息參數(shù)會(huì)在接收頁面的event.data查到);
在父頁面監(jiān)聽message事件,監(jiān)聽到了就讓登錄遮罩消失;
父傳子
同樣,在父窗口也可以使用postMassage 來傳遞消息到子頁面;
//父頁面 <button id="btn">傳遞消息</button> <iframe id='f' src="子頁面.html"></iframe> //子頁面 <div id="a"></div> //父頁面 <script> let oBtn=document.getElementById('btn'); let oFrame=document.getElementById('f'); oBtn.onclick=function(){ oFrame.contentWindow.postMessage('hello','*'); } </script> //子頁面 <script> window.addEventListener('message',function(){ if(event.data=='hello'){ document.getElementById('#a').innerText=event.data; } }) </script>
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Bootstrap每天必學(xué)之標(biāo)簽與徽章
Bootstrap每天必學(xué)之標(biāo)簽與徽章,對Bootstrap標(biāo)簽與徽章小編也了解的很少,希望通過這篇文章和大家更多的去學(xué)習(xí)Bootstrap標(biāo)簽與徽章,從中得到收獲。2015-11-11終于解決了IE8不支持?jǐn)?shù)組的indexOf方法
今天,測試報(bào)過來一個(gè)js bug, 在IE8下有個(gè)js錯(cuò)誤,但是在其它瀏覽器下(Firefox, Chrome, IE9)下面都很正常。后來調(diào)試發(fā)現(xiàn)原因是在IE8下,js數(shù)組沒有indexOf方法。2013-04-04

微信小程序?qū)崿F(xiàn)文字長按復(fù)制與一鍵復(fù)制功能全過程

小程序使用webview內(nèi)嵌h5頁面 wx.miniProgram.getEnv失效問題