pykend
pykend
发布于 2个月前

Trigger and listen events across iframes

最近做的几个软件项目,需要大量使用IFrame,IFrame与主窗体通信的问题自然浮现。

稍作研究,可知此问题的解决思路是这样的:

  1. IFrame只在内部触发消息和监听事件,也就是说,在IFrame加载的网页,并不知道自己被加载在IFrame中,它自顾自地触发和监听事件。
  2. 主窗体知道自己有IFrame,会主动向IFrame触发事件,同时向IFrame监听自己感兴趣的事件。

IFrame触发消息

function trigger(name, payload){
    $.event.trigger({
        type: name,
        payload: payload
    });
}

调用示例:

trigger('Event-B', {words: 'Hello! I\'m B.'});

IFrame监听事件

function listen(name, callback){
    function warn(warning){
        console && console.warn && console.warn('listen:', warning);
    }
    $(document).on(name, function(event){
        if(callback && callback.constructor === Function){
            callback(event.payload);
        }else{
            console.warn('callback should be a "Function" object');
        }
    });
}

调用示例:

listen('Event-A', function(payload){
    console && console.log && console.log('Event-A receieved. The payload is ' + JSON.stringify(payload));
    });

主窗体向IFrame触发事件

function triggerOnIFrame(iframe, name, payload){
    function warn(warning){
        console && console.warn && console.warn('triggerOnIFrame:', warning);
    }
    if(!name){
        warn('"name" of the event is excepted.');
    }else{
        var $iframe = $(iframe);
        if($iframe.length>0){
            $iframe.each(function(i, item){
                item.contentWindow.$(item.contentWindow.document).trigger({
                    type: name,
                    payload: payload
                });
            });
        }else{
            warn('\'jQuery selector \'' + iframe + '\')\' not found in DOM.' );
        }
    }
}

调用示例:

triggerOnIFrame('iframe#map', 'Event-A', {word: 'Hello! I\'m A.'});

主窗体监听IFrame事件

function listenOnIFrame(iframe, name, callback){
    function warn(warning){
        console && console.warn && console.warn('listenOnIFrame:', warning);
    }

    var $iframe = $(iframe);

    if($iframe.length>0){
        $iframe.each(function(i, item){
            $(item).on('load', function(){
                item.contentWindow.$(item.contentWindow.document).on(name, function(event){
                    if(callback && callback.constructor === Function){
                        callback(event.payload);
                        }else{
                            warn('"callback" should be a "Function" object');
                        }
                    });
            });
        });
    }else{
        warn('\'jQuery selector \'' + iframe + '\')\' not found in DOM.' );
    }
}

调用示例:

listenOnIFrame('iframe#map', 'Event-B', function(payload){
    console && console.log && console.log(payload);
});

参考链接: