通用Iframe跨域通信库实现

简介: 前言 前端在页面嵌入其他站点的页面时,常常会遇到跨域通信的问题,浏览器为了安全问题,限制了不同域名的JS直接调用。 解决方案 浏览器再限制跨域调用的同时,也预留了一个比较安全的通道。那就是message通道。

前言

前端在页面嵌入其他站点的页面时,常常会遇到跨域通信的问题,浏览器为了安全问题,限制了不同域名的JS直接调用。

解决方案

浏览器再限制跨域调用的同时,也预留了一个比较安全的通道。那就是message通道。 只要得到一个页面的window对象,都可以调用其postMessage的api,而不会有任何限制。而希望接受到其他页面message的页面只需要侦听这一消息即可。
发送者代码示例

var parentWindow = window.parent; //假设这是一个放在iframe的页面,那么这样可以得到其父页面的window对象
parentWindow.postMessage({
           data: 'test'
 }, '*')

侦听者代码示例

window.addEventListener('message', function(event) {

}, false);

经过以上几行简单的代码,就完成一个基本的页面通信了。

写一个通用的通信库

接下来对以上的代码进行改良,使其成为一个通用的iframe通信库。

代理端 iframe-proxy.js的内容

var IFRAME_PROXY = {
    invoke: function(ns, params, callback, source, domain) {
        try {
            var arr = ns.split('.');
            var target = window;
            for (var i = 0; i < arr.length; i++) {
                var t = arr[i]
                target = target[t];
            }
        } catch (error) {
            console.log(ns + 'not found, check your method.');
            return;
        }
        params.success = function(res) {
            source.postMessage({
                'type': 'QN_PROXY_CALLBACK',
                'params': res,
                'callback': callback,
                'code': 200
            }, domain);
        }

        params.error = function(res) {
            source.postMessage({
                'type': 'IFRAME_PROXY_CALLBACK',
                'params': res,
                'callback': callback,
                'code': 999
            }, domain);

        };
        target.invoke(params);
    }
}

window.addEventListener('message', function(event) {
    //console.log('received response:  ', event.data);
    var data = event.data;
    var domain = event.origin;
    var source = event.source;
    switch (data.type) {
        case 'IFRAME_PROXY':
            IFRAME_PROXY.invoke(data.ns, data.params, data.callback, source, domain);
            break;
    }
}, false);

调用端iframe-proxy-client.js

var __sourceWin__ = null;
var __callbackMap__ = {};
window.addEventListener('message', function(event) {
    var data = event.data;
    switch (data.type) {
        case 'IFRAME_PROXY_CALLBACK':
            var fn = data.callback;
            var isSuccess = data.code == 200;
            if (isSuccess) {
                __callbackMap__[fn].success(data.params);
            } else {
                __callbackMap__[fn].error(data.params);
            }
            break;
    }

});

function ___noop() {};
var IFRAME_PROXY = {
    invoke: function(ns, params) {
        var callbackId = 'qnproxy' + new Date().getTime() + Math.floor(Math.random() * 100000) + Math.floor(Math.random() * 100000);
        __callbackMap__[callbackId] = {
            success: params.success || ___noop,
            error: params.error || ___noop
        }
        for (var o in params) {
            if (typeof params[o] == 'function') {
                delete(params[o])
            }
        }
        window.parent.postMessage({
            type: 'IFRAME_PROXY',
            ns: ns,
            params: params,
            callback: callbackId
        }, '*')
    }
}

如何使用

在iframe的的页面引入iframe-proxy-client.js,在父页面引入 iframe-proxy.js, 假设子页面需要调用父页面的方法, Util.getName('abc'),那么调用

IFRAME_PROXY.invoke('Util.getName','abc', function(res) {
  //res就是父页面调用的函数结果
})

经过以上几步,就实现了一个通用了IFRAME通信库。

目录
相关文章
|
存储 Java 测试技术
|
缓存 前端开发 JavaScript
深入了解 Vite:快速、简洁、高效的前端构建工具(上)
深入了解 Vite:快速、简洁、高效的前端构建工具(上)
|
存储 机器学习/深度学习 算法
【数据结构与算法篇】深入浅出——二叉树(详解)
【数据结构与算法篇】深入浅出——二叉树(详解)
835 0
|
3月前
|
关系型数据库 MySQL 分布式数据库
安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景
PolarDB分布式轻量版采用软件输出方式,能够部署在您的自主环境中。PolarDB分布式轻量版保留并承载了云原生数据库PolarDB分布式版技术团队深厚的内核优化成果,在保持高性能的同时,显著降低成本。
|
4月前
|
开发框架 定位技术 API
AgentScope 与 MCP:实践、思考与展望
AgentScope 作为一款功能强大的开源多智能体开发框架,为开发者提供了智能体构建、工具使用、多智能体编排等全方位支持。
612 37
|
7月前
|
编解码 Linux 虚拟化
在Hyper-V虚拟化的图形处理中,怎么调整虚拟机的屏幕分辨率?
在Hyper-V虚拟化中,调整虚拟机屏幕分辨率对提升用户体验和确保应用程序兼容性至关重要。高分辨率可提供清晰图像、提高工作效率,并避免显示异常。调整方法包括通过增强会话模式、虚拟机内部设置或手动编辑配置文件。注意事项包括正确安装显卡驱动、避免过高分辨率及及时保存设置。
|
域名解析 存储 网络协议
一次读懂网络分层:应用层到物理层全解析
**网络五层模型简介:** 探索网络服务的分层结构,从应用层开始,包括HTTP(网页传输)、SMTP(邮件)、DNS(域名解析)和FTP(文件传输)协议。传输层涉及TCP(可靠数据传输)和UDP(高效但不可靠)。网络层由IP(路由数据包)、ICMP(错误报告)和路由器构成。数据链路层处理MAC地址和帧传输,物理层规定了电缆、连接器和信号标准。了解这些基础,有助于深入理解网络运作机制。
892 5
|
前端开发
CSS动画(动态导航栏)
CSS动画(动态导航栏)
|
数据采集 Python
Selenium爬取百度热搜榜单
Selenium爬取百度热搜榜单
295 0
Selenium爬取百度热搜榜单
|
安全 数据安全/隐私保护 Python
版权保卫战的新武器!揭秘数字水印如何成为知识产权的守护神!
【8月更文挑战第22天】数字水印技术在知识产权保护中至关重要。它通过在数字媒体中嵌入不可见信息(如版权标识),在不影响原内容的前提下实现作品的版权保护、防篡改及非法分发追踪。本文将概述数字水印的概念、技术原理(包括空间域与频域方法),并提供Python代码示例展示水印的嵌入与提取过程。此外,还将分享一个出版社如何运用数字水印成功维护自身版权的真实案例,以此展现数字水印在实际应用中的价值与潜力。
637 0