利用postMessage解決webview中iframe數(shù)據(jù)交互問題

最近在項目中遇到了一個在客戶端中的webview中嵌入iframe頁面的問題,但是嵌入的iframe無法自己撐開,所以需要webview中給iframe一個高度。

webview的Bug

這就比較尷尬了,因為webview肯定不知道iframe的高度,所以需要iframe給傳一個高度出來。

經(jīng)過一番查找之后,知道了一種很方便的方法-postMessage方法。

先來看看他的語法:

otherWindow.postMessage(data, origin, [transfer]);

otherWindow

  • 其他窗口的一個引用,比如iframe的contentWindow屬性、執(zhí)行window.open返回的窗口對象、或者是命名過或數(shù)值索引的window.frames。這里即可以是父窗口,也可以子窗口,兩者是可以相互傳遞數(shù)據(jù)的。

data

  • 將要發(fā)送到其他window的數(shù)據(jù)。它將會被結(jié)構(gòu)化克隆算法序列化(這個不懂是什么意思)。這意味著你可以不受什么限制的將數(shù)據(jù)對象安全的傳送給目標窗口而無需自己序列化?;臼鞘裁磪?shù)都可以,字符串、數(shù)字、對象、數(shù)組,都OK。

origin

  • 字符串參數(shù),指明目標窗口的源,協(xié)議+主機+端口號[+URL],URL會被忽略,所以可以不寫,這個參數(shù)是為了安全考慮,postMessage()方法只會將message傳遞給指定窗口,當然如果愿意也可以建參數(shù)設(shè)置為"*",這樣可以傳遞給任意窗口,如果要指定和當前窗口同源的話設(shè)置為"/"。

transfer(可選)

  • 是一串和message 同時傳遞的 Transferable 對象. 這些對象的所有權(quán)將被轉(zhuǎn)移給消息的接收方,而發(fā)送一方將不再保有所有權(quán)。(不懂是什么意思,一般沒有什么用吧,望大神指點)

父頁面獲取iframe頁面信息:

demo我放在github上的:
demo地址:父頁面獲取iframe頁面信息

父頁面:

<body>
    <p>我是父頁面</p>
    <p>接收到的iframe信息是:<span id="content"></span></p>
    <iframe src="/btoa/b.html" frameborder="0" marginheight="0" marginwidth="0"></iframe>
    <script>
        // event 參數(shù)中有 data 屬性,就是iframe頁面發(fā)送過來的數(shù)據(jù)
         window.addEventListener("message", function(event) {
             // 把iframe頁面發(fā)送過來的數(shù)據(jù)顯示在父頁面中
           document.getElementById("content").innerHTML= event.data;
         }, false);
    </script>
</body>

iframe頁面

<body>
    <p>我是iframe頁面</p>
    <div>發(fā)送的信息是:<input id="iframe" type="text"><input id="sendBtn" type="button" value="發(fā)送"></div>
    <script>
        // 點擊按鈕后向父頁面發(fā)送數(shù)據(jù)
        document.getElementById('sendBtn').onclick = function() {
            // window.parent代表父頁面
            window.parent.postMessage(document.getElementById("iframe").value, '*');
        }
    </script>
</body>


iframe頁面獲取父頁面信息:

demo我放在github上的:
demo地址:iframe頁面獲取父頁面信息

父頁面:

<body>
    <p>我是父頁面</p>
    <div>發(fā)送的信息是:<input id="iframe" type="text"><input id="sendBtn" type="button" value="發(fā)送"></div>
    <iframe src="/atob/b.html" frameborder="0" marginheight="0" marginwidth="0"></iframe>
    <script>
        // 點擊按鈕后向iframe頁面發(fā)送數(shù)據(jù)
        document.getElementById('sendBtn').onclick = function() {
            // window.frames[0]代表第一個iframe頁面
            window.frames[0].postMessage(document.getElementById("iframe").value, '*');
        }
    </script>
</body>

iframe頁面

<body>
    <p>我是iframe頁面</p>
    <p>接收到的父頁面信息是:<span id="content"></span></p>
    <script>
        // event 參數(shù)中有 data 屬性,就是父頁面發(fā)送過來的數(shù)據(jù)
         window.addEventListener("message", function(event) {
             // 把父頁面發(fā)送過來的數(shù)據(jù)顯示在父頁面中
           document.getElementById("content").innerHTML= event.data;
         }, false);
    </script>
</body>

通過這兩個簡單的例子我們會發(fā)現(xiàn)postMessage的強大之處,有了postMessage,我們甚至可以在兩個iframe之間傳送數(shù)據(jù),只需要一個共同的父元素做中間頁。


需要注意的地方:

兼容性:

caniuse

通過圖上可以看出,基本大部分的都能兼容的,但是需要注意一下這句話。

Internet Explorer 8 and 9, and Firefox versions 6.0 and below only support strings as postMessage's message.(ie 8和9,和Firefox 6.0及以下版本只支持字符串作為postMessage的消息。)

所以如果需要支持這些版本的需要注意data只能是字符串。

安全性:

在線上進行交互時,最好做好安全措施,對于postMessage,最好采用“雙向安全機制”。發(fā)送方發(fā)送數(shù)據(jù)的時候,確認接受方的源(所以最好不要用*),而接受方監(jiān)聽到message事件后,也可以用event.origin判斷是否來自于正確可靠的發(fā)送方。并且最好做一下傳遞數(shù)據(jù)的數(shù)據(jù)類型校驗。如以下代碼:

function checkMessage(event) {
    // 只獲取需要的域,并非所有都可以跨域
    if (event.origin != "need domain") {
        return false;
    }
    
    var data = event.data;
    // 傳輸數(shù)據(jù)類型校驗
    if (typeof(data) !== 'object') {
        return false;
    }

    // data 的type中包含xxx則為xxx需要字段。
    return data.type === "xxx";
};

并且通過不同的type可以處理不同的數(shù)據(jù),如以下代碼:

switch (checkMessage(event)) {
    case 'height':
        $("#bet_"+e.data.id).css("height", (e.data.height+1) + "px");
        break;
    case 'jumpDown':
        window.location.href = downUrl;
        break;
    default:
        break;
}

順便貼一下本人的博客:yellowlemon的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,030評論 25 709
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 861評論 0 0
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 622評論 0 0
  • 秋風瀟瀟寒霜起,欲訴衷腸,錦書難寄。漿聲杳杳雁無跡,一彎新月,數(shù)首舊詞。仔細思量未趁意,花未爽約,人誤佳期。菊瘦花...
    簡書作者木瓜閱讀 472評論 9 8
  • 這篇文章適合大部分像我這種需要做PPT、有點基礎(chǔ)而且懶不想加班的職場人,以及需要自己做圖片的苦逼新媒體工作從業(yè)者。...
    肉肉_Jade閱讀 601評論 0 9

友情鏈接更多精彩內(nèi)容