iframe頁面相互調(diào)用方法

關(guān)鍵詞:iframe,跨域,vue
最近的項(xiàng)目中嵌入了外部的iframe惶我,想跨域調(diào)用自己頁面的方法傅联,點(diǎn)擊iframe中的返回按鈕嫂便,返回到父級的上一級頁面拗盒,因?yàn)槭亲约旱捻?xiàng)目是單頁應(yīng)用,所以無法直接使用window.location.href恰力,這個(gè)需求讓我頭疼了兩天(包括衍生出來的問題)叉谜,解決了這個(gè)問題之后我決定總結(jié)一下,首先從簡單的開始:

  • 基本概念:

window.self: 當(dāng)前窗口自身的引用
window.parent: 上一級父窗口的引用
window.top: 最頂層窗口的引用
當(dāng)頁面中不存在 iframe 嵌套時(shí)踩萎,則三者均是當(dāng)前窗口自身的引用停局。

  • 同域iframe相互調(diào)用:
    1. 子頁面調(diào)用父頁面方法:window.parent.fatherFn();
    2. 父頁面調(diào)用子頁面方法: window.sonFrameName.sonFn();(sonFrameName是iframe的name值)

下面才是重點(diǎn)(一般嵌入iframe的應(yīng)用應(yīng)該都是跨域的吧)

  • 跨域iframe相互調(diào)用:

首先要了解html5的api——window.postMessage,我實(shí)現(xiàn)跨域調(diào)用都是基于postMessage方法的。

語法:

otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一個(gè)引用香府,比如iframe的contentWindow屬性董栽、執(zhí)行window.open返回的窗口對象、或者是命名過或數(shù)值索引的window.frames
message
將要發(fā)送到其他 window的數(shù)據(jù)企孩。
targetOrigin
通過窗口的origin屬性來指定哪些窗口能接收到消息事件锭碳,其值可以是字符串"*"(表示無限制)或者一個(gè)URI。 (由于安全原因最好不要使用"*")
transfer
可選參數(shù)(基本用不上勿璃,我也沒看懂官方的解釋??)

接收消息:

在window對象上監(jiān)聽派遣的message擒抛,使用window.addEventListener('message',fn);或者使用window.onmessage = fn;推汽,我在項(xiàng)目中使用了后者。無論使用哪種方法都要注意調(diào)用方法結(jié)束后要解綁——window.removeEventListener('message',fn);歧沪,否則很可能會出現(xiàn)重復(fù)調(diào)用的情況民泵。
這里的fn有一個(gè)event參數(shù),拿到的是一個(gè)叫做MessageEvent的對象槽畔,chrome控制臺輸出是這樣的

MDN上列出了三個(gè)重要的參數(shù)
data
從其他 window 中傳遞過來的對象栈妆。 (即其他頁面發(fā)送過來的消息)
origin
調(diào)用 postMessage 時(shí)消息發(fā)送方窗口的 origin. 這個(gè)字符串由 協(xié)議、“://“厢钧、域名鳞尔、“ : 端口號”拼接而成。 (即頁面的url) 更新:之前沒仔細(xì)看早直,這個(gè)origin就是定義上的意思寥假,如https://www.janshu.com或者http://www.aaa.com:8088
source
對發(fā)送消息的窗口對象的引用; 您可以使用此來在具有不同origin的兩個(gè)窗口之間建立雙向通信。(按照MDN上的例子可以在接受message的回調(diào)中將source作為回信的對象霞扬,也就是己方頁面)

按照MDN上的要求糕韧,為了避免跨站點(diǎn)腳本攻擊,在接收到消息的回調(diào)中需要對origin進(jìn)行判斷喻圃,如果不是正確的消息來源地址萤彩,需要return。
下面上自己寫的demo:(x.x.x.x均為本機(jī)ip地址)
父頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<button id="btn">toSon</button>
<iframe src="http://x.x.x.x:8082/iframe2.html" frameborder="0" name="son"></iframe>
<body>
    <script src="http://x.x.x.x:8081/js/jquery.min.js"></script>
    <script>
        $(function(){
            window.addEventListener('message',function(e){
                console.log(e);
            })
            $('#btn').on('click',function(){
                window.son.postMessage('fromFather','http://x.x.x.x:8082/iframe2.html');
            })
            
        })
    </script>
</body>
</html>

子頁面(判斷了消息來源)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button id="btn">toFather</button>
    <script src="http://x.x.x.x:8082/js/jquery.min.js"></script>
    <script>
        $(function(){
            $('#btn').on('click',function(){
                window.top.postMessage('hi','http://x.x.x.x:8081/iframe1.html');
            })
            window.addEventListener('message',function(e){
                if(e.origin!=='http://x.x.x.x:8081'){
                    return;
                }
                //父頁面點(diǎn)擊按鈕斧拍,執(zhí)行子頁面的方法
                console.log(e.data);
            })
        })
    </script>
</body>
</html>

我目前的項(xiàng)目使用的是vue雀扶,來看看單頁應(yīng)用中的用法,以及解綁的方法(偽代碼)

<template>
    <div class="full-width full-height drawOnline fix-ios-scroll containHeader">
        <MainHeader title="在線繪圖" :backURL="backURL"></MainHeader>
        <iframe :src="src"></iframe>
    </div>
</template>
<script>
......
export default {
        data(){
            return{
                backURL:'...'
            }
        },
        mounted(){
            let _this = this;
            //每次生成的實(shí)例都不同(this不同)肆汹,所以使用addEventListener無法解綁
            window.onmessage = function (e) {
                if(e.data=='backPhoto'){//從iframe頁面中接收到的消息
                    _this.iframeBack();
                }
            }
        },
        destroyed(){
            window.removeEventListener('message',this.iframeBack,false);
        },
        computed:{
            src(){
                return '......'
            }
        },
        methods:{
            iframeBack(){
                this.$router.push(this.backURL);
            }
        }
        ......
}
</script>

首先整體流程是在自己的頁面中嵌入了一個(gè)外部的iframe愚墓,在iframe中點(diǎn)擊返回按鈕之后,當(dāng)前頁面關(guān)閉返回上一個(gè)頁面昂勉。iframe內(nèi)點(diǎn)擊的返回按鈕之后浪册,向當(dāng)前頁面發(fā)送了'backPhoto'這個(gè)消息,當(dāng)前頁面接收到這個(gè)消息之后(當(dāng)時(shí)直接采取的判斷消息名而沒有判斷來源路徑)執(zhí)行路由跳轉(zhuǎn)岗照,當(dāng)前實(shí)例包括iframe都會被銷毀村象,因此在銷毀之前執(zhí)行了解綁,這樣可以保證每次進(jìn)入這個(gè)頁面window對象重新監(jiān)聽message,iframeBack這個(gè)方法不會重復(fù)調(diào)用谴返。
一開始我是沒注意到解綁這個(gè)問題的煞肾,測試也沒發(fā)現(xiàn)這個(gè)問題,直到我進(jìn)入這個(gè)頁面測其它的功能點(diǎn)返回的時(shí)候才發(fā)現(xiàn)返回的路由地址不對(因?yàn)槁酚赡┪灿衖d嗓袱,而返回的時(shí)候只會返回到第一個(gè)id的地址),通過調(diào)試發(fā)現(xiàn)iframeBack這個(gè)方法調(diào)用了多次习绢,原因在于每進(jìn)入一次這個(gè)頁面window就多監(jiān)聽了一次message渠抹,所以需要在銷毀實(shí)例的時(shí)候執(zhí)行解綁蝙昙。
而怎么解綁這個(gè)問題也是困擾了我半天,一開始無論怎么解綁都不成功梧却,直到我在某個(gè)論壇看到了一個(gè)解決方法:使用onmessage而不是用addEventListener進(jìn)行綁定奇颠,因?yàn)槊恳淮沃匦律蓪?shí)例之后iframeBack函數(shù)與上一次都不同,所以remove并不能準(zhǔn)確的移除上一次綁定的函數(shù)放航。所幸最終還是皆大歡喜完結(jié)撒花了烈拒。

轉(zhuǎn)載請注明出處http://www.reibang.com/p/17c1cf2f4426

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市广鳍,隨后出現(xiàn)的幾起案子荆几,更是在濱河造成了極大的恐慌,老刑警劉巖赊时,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吨铸,死亡現(xiàn)場離奇詭異,居然都是意外死亡祖秒,警方通過查閱死者的電腦和手機(jī)诞吱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來竭缝,“玉大人房维,你說我怎么就攤上這事√е剑” “怎么了握巢?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長松却。 經(jīng)常有香客問我暴浦,道長,這世上最難降的妖魔是什么晓锻? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任歌焦,我火速辦了婚禮,結(jié)果婚禮上砚哆,老公的妹妹穿的比我還像新娘独撇。我一直安慰自己,他們只是感情好躁锁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布纷铣。 她就那樣靜靜地躺著,像睡著了一般战转。 火紅的嫁衣襯著肌膚如雪搜立。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天槐秧,我揣著相機(jī)與錄音啄踊,去河邊找鬼忧设。 笑死,一個(gè)胖子當(dāng)著我的面吹牛颠通,可吹牛的內(nèi)容都是我干的址晕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼顿锰,長吁一口氣:“原來是場噩夢啊……” “哼谨垃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起硼控,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤刘陶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后淀歇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體易核,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年浪默,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了牡直。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纳决,死狀恐怖碰逸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情阔加,我是刑警寧澤饵史,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站胜榔,受9級特大地震影響胳喷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夭织,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一吭露、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尊惰,春花似錦讲竿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膀捷,卻和暖如春迈嘹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背担孔。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工江锨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吃警,地道東北人糕篇。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓啄育,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拌消。 傳聞我的和親對象是個(gè)殘疾皇子挑豌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1. 什么是跨域? 跨域一詞從字面意思看墩崩,就是跨域名嘛氓英,但實(shí)際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 510評論 0 0
  • 什么是跨域 跨域鹦筹,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本铝阐。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實(shí)...
    Yaoxue9閱讀 1,286評論 0 6
  • 什么是跨域 跨域铐拐,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本徘键。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實(shí)...
    他方l閱讀 1,059評論 0 2
  • 什么是跨域 跨域遍蟋,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本吹害。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript實(shí)...
    HeroXin閱讀 831評論 0 4
  • 女兒每周回來虚青,我們母女都會聊談很多它呀。 老媽劲够,上次我發(fā)給你的短信“媽媽班眯,我愛你”,你一定奇怪吧收毫? 有點(diǎn)奢人,怎么突然想起...
    熱冰_1c24閱讀 574評論 1 5