成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

messengerjs iframe 跨域傳數(shù)據(jù)

tomorrowwu / 1842人閱讀

摘要:剛來公司時做得第一個項目是跨部門合作,使用了來做通信,十分簡單,代碼不長,這里分析一下間通信的實現(xiàn)方式源碼消息前綴建議使用自己的項目名避免多項目之間的沖突注意消息前綴應(yīng)使用字符串類型類消息對象往發(fā)送消息出于安全考慮發(fā)送消息會帶上前綴

剛來公司時做得第一個項目是跨部門合作,使用了MessengerJS來做通信,十分簡單,MessengerJS代碼不長,這里分析一下iframe間通信的實現(xiàn)方式

源碼

/**
 *     __  ___
 *    /  |/  /___   _____ _____ ___   ____   ____ _ ___   _____
 *   / /|_/ // _  / ___// ___// _  / __  / __ `// _  / ___/
 *  / /  / //  __/(__  )(__  )/  __// / / // /_/ //  __// /
 * /_/  /_/ \___//____//____/ \___//_/ /_/ \__, / \___//_/
 *                                        /____/
 *
 * @description MessengerJS, a common cross-document communicate solution.
 * @author biqing kwok
 * @version 2.0
 * @license release under MIT license
 */

window.Messenger = (function(){

    // 消息前綴, 建議使用自己的項目名, 避免多項目之間的沖突
    // !注意 消息前綴應(yīng)使用字符串類型
    var prefix = "[PROJECT_NAME]",
        supportPostMessage = "postMessage" in window;

    // Target 類, 消息對象
    function Target(target, name, prefix){
        var errMsg = "";
        if(arguments.length < 2){
            errMsg = "target error - target and name are both required";
        } else if (typeof target != "object"){
            errMsg = "target error - target itself must be window object";
        } else if (typeof name != "string"){
            errMsg = "target error - target name must be string type";
        }
        if(errMsg){
            throw new Error(errMsg);
        }
        this.target = target;
        this.name = name;
        this.prefix = prefix;
    }

    // 往 target 發(fā)送消息, 出于安全考慮, 發(fā)送消息會帶上前綴
    if ( supportPostMessage ){
        // IE8+ 以及現(xiàn)代瀏覽器支持
        Target.prototype.send = function(msg){
            this.target.postMessage(this.prefix + "|" + this.name + "__Messenger__" + msg, "*");
        };
    } else {
        // 兼容IE 6/7
        Target.prototype.send = function(msg){
            var targetFunc = window.navigator[this.prefix + this.name];
            if ( typeof targetFunc == "function" ) {
                targetFunc(this.prefix + msg, window);
            } else {
                throw new Error("target callback function is not defined");
            }
        };
    }

    // 信使類
    // 創(chuàng)建Messenger實例時指定, 必須指定Messenger的名字, (可選)指定項目名, 以避免Mashup類應(yīng)用中的沖突
    // !注意: 父子頁面中projectName必須保持一致, 否則無法匹配
    function Messenger(messengerName, projectName){
        this.targets = {};
        this.name = messengerName;
        this.listenFunc = [];
        this.prefix = projectName || prefix;
        this.initListen();
    }

    // 添加一個消息對象
    Messenger.prototype.addTarget = function(target, name){
        var targetObj = new Target(target, name,  this.prefix);
        this.targets[name] = targetObj;
    };

    // 初始化消息監(jiān)聽
    Messenger.prototype.initListen = function(){
        var self = this;
        var generalCallback = function(msg){
            if(typeof msg == "object" && msg.data){
                msg = msg.data;
            }
            
            var msgPairs = msg.split("__Messenger__");
            var msg = msgPairs[1];
            var pairs = msgPairs[0].split("|");
            var prefix = pairs[0];
            var name = pairs[1];

            for(var i = 0; i < self.listenFunc.length; i++){
                if (prefix + name === self.prefix + self.name) {
                    self.listenFunc[i](msg);
                }
            }
        };

        if ( supportPostMessage ){
            if ( "addEventListener" in document ) {
                window.addEventListener("message", generalCallback, false);
            } else if ( "attachEvent" in document ) {
                window.attachEvent("onmessage", generalCallback);
            }
        } else {
            // 兼容IE 6/7
            window.navigator[this.prefix + this.name] = generalCallback;
        }
    };

    // 監(jiān)聽消息
    Messenger.prototype.listen = function(callback){
        var i = 0;
        var len = this.listenFunc.length;
        var cbIsExist = false;
        for (; i < len; i++) {
            if (this.listenFunc[i] == callback) {
                cbIsExist = true;
                break;
            }
        }
        if (!cbIsExist) {
            this.listenFunc.push(callback);
        }
    };
    // 注銷監(jiān)聽
    Messenger.prototype.clear = function(){
        this.listenFunc = [];
    };
    // 廣播消息
    Messenger.prototype.send = function(msg){
        var targets = this.targets,
            target;
        for(target in targets){
            if(targets.hasOwnProperty(target)){
                targets[target].send(msg);
            }
        }
    };

    return Messenger;
})();

下面主要分析代碼結(jié)構(gòu)

supportPostMessage變量

用來檢測當(dāng)前瀏覽器是否支持postMessage

postMessage是HTML5引入的通信API,它可以避開同源策略的限制,實現(xiàn)安全的跨域通信

向外界窗口發(fā)送消息

otherWindow.postMessage(message, targetOrigin);

otherWindow: 指目標(biāo)窗口,也就是給哪個window發(fā)消息,是 window.frames 屬性的成員或者由 window.open 方法創(chuàng)建的窗口

message: 是要發(fā)送的消息,類型為 String、Object (IE8、9 不支持),一般使用json數(shù)據(jù)

targetOrigin: 是限定消息接收范圍,協(xié)議+主機+端口號[+URL],URL會被忽略,所以可以不寫,不限制請使用 ‘*’

接受信息的message事件

var onmessage = function (event) {
    var data = event.data;
    var origin = event.origin;
    //do someing
};
if (typeof window.addEventListener != "undefined") {
    window.addEventListener("message", onmessage, false);
} else if (typeof window.attachEvent != "undefined") {
    //for ie
    window.attachEvent("onmessage", onmessage);
}

注意:ie6/7不支持postMessage,因此在ie6/7中跨域通信通常使用window.name

window.name的美妙之處:name 值在不同的頁面(甚至不同域名)加載后依舊存在,并且可以支持非常長的 name 值(2MB)

window.navigator有與window.name類似的特性,而且可以保存回調(diào)方法

MessengerJS的實現(xiàn)思路是高級瀏覽器使用postMessage,不支持postMessage的使用window.navigator來保存回調(diào)方法

Target類

消息類,發(fā)送執(zhí)行者

function Target(target, name){
    this.target = target;
    this.name = name;
}

Target.prototype.send = function(msg){
    // 發(fā)送消息
};
Messenger類

信使類,創(chuàng)建多個消息對象,注冊多個監(jiān)聽事件,每一個消息對象的廣播消息會被這個信使類下面的所有監(jiān)聽事件接收到

function Messenger(messengerName, projectName){
    this.targets = {};
    this.name = messengerName;
    this.listenFunc = [];
    this.initListen();
}

// 添加一個消息對象
Messenger.prototype.addTarget = function(target, name){};

// 初始化消息監(jiān)聽
Messenger.prototype.initListen = function(){};

// 監(jiān)聽消息
Messenger.prototype.listen = function(callback){};

// 注銷監(jiān)聽
Messenger.prototype.clear = function(){};

// 廣播消息
Messenger.prototype.send = function(msg){};

實現(xiàn)邏輯是:

initListen方法初始化,將generalCallback回調(diào)方法注冊到message監(jiān)聽中

addTarget將消息對象添加到targets對象中

listen方法將監(jiān)聽方法添加到listenFunc數(shù)組中

send方法執(zhí)行每一個target對象的send方法

target對象的send方法執(zhí)行,觸發(fā)了message監(jiān)聽,觸發(fā)了generalCallback的執(zhí)行,從而執(zhí)行了listenFunc數(shù)組中的方法

在postMessage的注冊回調(diào)方法里加了一個回調(diào)方法組listenFunc

在postMessage的監(jiān)聽觸發(fā)方法外加了一層集體觸發(fā)對象targets

從而達(dá)到了廣播的效果

postMessage本身可以實現(xiàn)廣播的效果,但是MessengerJS為了兼容,限制了postMessage的能力,自行實現(xiàn)了廣播

使用場景

MessengerJS來做iframe通信解決的最常見的問題是,在主頁面為iframe留足高度

parent頁面

var messenger = new Messenger("parent");
    var iframe = document.getElementById("iframepage");
    messenger.addTarget(iframe.contentWindow, "iframe");

    messenger.listen(function (msg) {
        var result = parseInt(msg, 10) + 20;

        if (result < mainWindowHeight) {
            result = mainWindowHeight;
        }
        $("#iframepage").height(result);
});

iframe頁面

// iframe跨域傳數(shù)據(jù)
var messenger = new Messenger("iframe");
messenger.addTarget(window.parent, "parent"); 

// 跨域傳main 高度
var height = $(".main").height();
messenger.targets["parent"].send(height);

messenger.listen(function (msg) {

});
總結(jié)

postMessage是一個用于安全的使用跨源通信的方法,幫助web開發(fā)回歸正軌

MessengerJS實現(xiàn)效果很好,即便做頻繁的交互,也不會有明顯的卡頓,不過時代在進(jìn)步,以后可能會很少用到這樣的兼容了

官方博文看這里:MessengerJS

本文轉(zhuǎn)載自筆者個人博客:Gaoxuefeng"s Blog

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79403.html

相關(guān)文章

  • messengerjs iframe 域傳數(shù)據(jù)

    摘要:消息前綴建議使用自己的項目名避免多項目之間的沖突類消息對象往發(fā)送消息出于安全考慮發(fā)送消息會帶上前綴以及現(xiàn)代瀏覽器支持兼容信使類添加一個消息對象初始化消息監(jiān)聽剝離消息前綴兼容監(jiān)聽消息廣播消息用法頁面頁面跨域傳數(shù)據(jù)跨域傳高度 messengerjs /** * __ ___ *...

    qpwoeiru96 評論0 收藏0
  • 附實例!實現(xiàn)iframe父窗體與子窗體的通信

    摘要:小結(jié)小結(jié)本文主要是介紹了一個方案及其使用方法,來解決父窗體與子窗體的通信問題。同時提供了一個完整的實例,可以實現(xiàn)子窗體向父窗體傳遞消息,父窗體通過監(jiān)聽消息事件,來獲取子窗體消息的目的。歡迎大家前往騰訊云+社區(qū),獲取更多騰訊海量技術(shù)實踐干貨哦~ 本文由前端林子發(fā)表于云+社區(qū)專欄 本文主要會介紹如何基于MessengerJS,實現(xiàn)iframe父窗體與子窗體間的通信,傳遞數(shù)據(jù)信息。同時本文會提...

    xiaochao 評論0 收藏0
  • 關(guān)于跨域簡單總結(jié)

    摘要:開發(fā)者需要在中設(shè)置屬性為跨域是的簡稱這是一種利用瀏覽器漏洞解決跨域的辦法腳本元素可以不受瀏覽器同源策略的限制。 什么是瀏覽器同源策略? 同源是指,域名,協(xié)議,端口號均相同,如圖: showImg(https://segmentfault.com/img/bV9rAO?w=1088&h=394); 注意:localhost和127.0.0.1雖然都指向本機,但也是跨域. 瀏覽器同源策略(...

    learning 評論0 收藏0
  • iframe跨域POST提交

    摘要:說到跨域,就不得不提起瀏覽器的同源策略。跨域無刷新提交跨域的方法有很多,像等等,由于項目中用到了進(jìn)行跨域,所以本文主要總結(jié)一下如何利用進(jìn)行無刷新提交。為了拿到返回回來的,需要使用一個函數(shù),函數(shù)名后臺已經(jīng)告知。 以前在面試的時候經(jīng)常遇到問關(guān)于跨域的事兒,所以自己對跨域有一定的概念性了解,知道什么是跨域以及解決跨域的方法,但是具體實際從來沒有操作過,直到最近在公司項目中,遇到了一個需要使i...

    wwq0327 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<