跨域从子页面设置父页面iframe高度(前提,两个域名下都有操作权限)

本文介绍了一种解决跨域环境下调整iframe高度的方法。通过在父页面同一域名下设置专门页面来接收子页面传递的高度信息,并据此调整iframe的高度。
之前在论坛里看到有个同学问关于跨域调整iframe高度的问题,正好之前解决过类似问题,鉴于此问题还是有一定的通用性,索性总结一下,记录于此。

具体思路如下:



父页面域名为 : www.a.com

IFRAME里子页面域名为 : www.b.com


1.在父级页面所在域名(www.a.com)下设置一个文件,(用来设置IFRAME的高度)比如:http://www.a.com/setHeight.html

2.在子级页面加载完毕后,计算当前页面高度付给一个变量cheight,然后动态创建一个iframe,src是http://www.a.com/setHeight.html#cheight;

3.通过在setHeight.html页面中parent.parent.document.getElementById('iframeid')来调整iframe的高度

4.解释一下,在子页面里动态创建的iframe跟当前子页面的父级页面是同一个域名,这样就不存在跨域问题了。



举例:
         假设父页面的域名是www.a.com,页面名字是 A.html;子页面的域名是www.b.com,页面名字是 B.html

父页面 A.html的内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta content="text/html; charset=gb2312" http-equiv="Content-Type">
</head>
    <body>
    <iframe height='200px' id='iframe1' src="http://www.b.com/B.html"></iframe>
</body>
</html>




父级页面所在域名下的用于调节iframe高度的页面 setHeight.html内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta content="text/html; charset=gb2312" http-equiv="Content-Type">
</head>
    <body>
        <div></div>
        <script type="text/javascript">
            window.onload = function()
            {
                var b_iframe = parent.parent.document.getElementById("iframe1");
                var hash_url = window.location.hash.split("#");
                var hash_height = hash_url[1]+"px";
                b_iframe.style.height = hash_height;
            }
        </script>
    </body>
</html>



子页面 B.html内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
</head>
<body style="background-color:#ccc">
    <div style="height:600px;">sdfsfsssfsfs</div>
    <script>
        window.onload = function()
        {
            var iframe = document.createElement("iframe");
            iframe.width='0px';
            iframe.height='0px';
            var currentheight = document.body.scrollHeight;
            iframe.src='http://www.a.com/setHeight.html#'+currentheight;
            document.body.appendChild(iframe);
        }
    </script>
</body>
</html>


可见默认的iframe高度是200px,而iframe中B.html的实际高度至少为600px,当B.html加载完成时,会自动调整其父页面iframe的高度

<think> 我们之前讨论的是页面调用父页面函数的方法,现在用户明确询问如何调用父页面函数(即非全局函数,可能是在某个作用内的函数)。这需要更精细的处理,因为函数可能不在全局作用(window)上。 关键点: 1. 如果是全局函数,可以直接通过parent.window.functionName调用(同)。 2. 如果是父页面某个局部作用内的函数,通常无法直接调用(因为函数作用限制)。此时需要父页面将函数暴露到全局,或者通过其他方式(如事件、消息)来间接调用。 因此,解决方案分为同两种情况,且需要根据函数是否为全局函数来分别处理。 同场景: - 如果父页面的函数是全局的(直接挂在window对象上),页面可以直接通过parent.window.functionName()调用。 - 如果函数不是全局的(例如在一个闭包内),那么需要父页面提供全局的访问接口(例如将函数挂载到window对象上),或者通过事件机制(如自定义事件)来触发。 场景: - 必须使用postMessage,且父页面需要监听message事件,并根据消息内容调用相应的函数(无论该函数是全局还是局部的,因为在父页面自己的执行环境中可以访问)。 因此,针对用户的问题“页面调用父页面函数”,这里的“函数”我们理解为非全局函数。那么需要父页面配合,提供一个全局的接口(桥梁)来调用这个函数。 具体实现步骤: 一、同且函数非全局的情况(需要父页面配合): 1. 父页面在全局创建一个对象(作为桥梁),例如:window.bridge = {} 2. 父页面将需要被页面调用的函数挂载到这个对象上,例如:window.bridge.childFunction = function() { ... } 3. 页面通过parent.window.bridge.childFunction()调用 二、且函数非全局的情况: 同样需要父页面配合,因为时只能通过postMessage通信,所以父页面在收到消息后需要自己调用内部的函数。步骤: 1. 父页面监听message事件,然后根据消息内容调用自己的函数(这个函数可以是非全局的,只要在父页面的事件监听器的作用链上能访问到即可)。 2. 页面通过postMessage发送请求。 示例代码: 同情况(非全局函数): - 父页面(function() { // 这是一个局部作用 function myLocalFunction(param) { console.log('父页面局部函数被调用,参数:', param); } // 将函数挂载到全局桥梁对象 window.bridge = { callLocalFunction: function(param) { myLocalFunction(param); // 通过桥梁暴露出去 } }; })(); - 页面: parent.window.bridge.callLocalFunction('来自页面的参数'); 情况(非全局函数): - 父页面(function() { function myLocalFunction(param) { console.log('父页面局部函数被调用,参数:', param); } window.addEventListener('message', function(event) { // 安全验证:检查来源 if (event.origin !== 'https://页面域名') return; try { const message = JSON.parse(event.data); if (message.action === 'callLocalFunction') { myLocalFunction(message.param); // 调用局部函数 } } catch (e) { console.error('解析消息出错', e); } }); })(); - 页面: const message = JSON.stringify({ action: 'callLocalFunction', param: '来自页面的参数' }); window.parent.postMessage(message, 'https://父页面域名'); 注意事项: 1. 时,父页面务必验证event.origin,确保消息来自可信源。 2. 如果函数需要返回值,则场景下需要通过postMessage将结果发送回页面(双向通信),但这样会增加复杂性,建议尽量避免。 由于这种调用方式需要父页面紧密配合,特别是父页面需要预先设置桥梁或监听器,因此在实际开发中要确保双方约定好通信协议。 如果可能,尽量将需要调用的函数放在父页面的全局作用下,这样可以简化调用(同时)。 相关问题: 1. 如何安全地实现父页面的双向通信? 2. 同下,如何避免全局命名冲突? 3. 父页面如何调用页面的内部函数? 4. 使用postMessage时如何传输复杂数据结构? </think> ### 页面调用父页面非全局函数的实现方法 当需要调用的不是全局函数(如闭包内的函数或模块私有函数)时,需要通过以下方案间接实现: #### 📌 方案一:父页面暴露访问接口(推荐) 在父页面创建"桥梁"对象提供访问入口: ```javascript // 父页面代码 window.bridge = { // 创建全局桥梁对象[^1] callChildFunction: (param) => { // 此处访问实际的目标函数 internalChildFunction(param); } }; function internalChildFunction(param) { console.log("函数被调用", param); } ``` ```javascript // 页面调用 parent.window.bridge?.callChildFunction("参数"); ``` #### 📌 方案二:自定义事件通信 通过事件机制解耦父页面: ```javascript // 父页面监听事件 window.addEventListener('child-function-call', (e) => { internalChildFunction(e.detail.param); // 触发目标函数[^2] }); // 页面发起事件 const event = new CustomEvent('child-function-call', { detail: { param: "数据" }, bubbles: true }); parent.document.dispatchEvent(event); // 向父文档派发事件[^2] ``` #### 🌐 场景专用方案 ```javascript // 页面发送请求 parent.postMessage(JSON.stringify({ type: "FUNCTION_CALL", functionId: "childFunc123", // 函数标识符 args: ["参数1", 2] }), 'https://parent-domain.com'); // 父页面处理 window.addEventListener('message', (e) => { if (e.origin !== 'https://child-domain.com') return; const { type, functionId, args } = JSON.parse(e.data); if (type === "FUNCTION_CALL") { functionRegistry[functionId]?.(...args); // 通过注册表调用[^3] } }); ``` #### ️ 关键注意事项 1. **封装保护**:通过接口层封装内部函数,避免直接暴露实现细节[^1] 2. **命名空间**:桥梁对象使用唯一命名防止冲突(如`window.APP_BRIDGE`) 3. **权限控制**:时严格验证`event.origin`并限定可用函数ID[^3] 4. **内存管理**:长期存在的桥梁对象需注意内存泄漏问题 > 最佳实践:对于现代前端架构,建议采用**微前端通信方案**(如`qiankun`的`initGlobalState`或`single-spa`事件总线)替代原始API调用[^2]。 --- ### 🔍 相关问题 1. 如何防止桥梁对象被非法篡改? 2. 微前端架构中主应用通信有哪些标准方案? 3. 自定义事件在浏览器场景下有哪些兼容性问题? 4. 如何在React/Vue组件中安全地暴露函数给iframe页面? [^1]: 桥梁对象封装方案 [^2]: 自定义事件通信机制 [^3]: 函数注册表实现
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值