iframe中调用父窗口方法

本文介绍了一个使用eval进行跨窗口方法调用的JavaScript函数示例。该函数通过遍历父窗口的所有frames来查找并调用指定的回调函数。如果找到对应的函数,则通过eval执行该函数,并传入相应的参数。
	function callFatherMethod(val){
		let callback = '${callback}';

		if(callback!=null && callback!=undefined){
			let evalStr = null;
			
			//console.log(parent);
			let frameSize = parent.frames.length;

			for(let i=0; i<frameSize; i++){
				let findCallBack = "parent["+i+"]."+callback;
                
                //判断父窗口有没有此方法
				if(eval(findCallBack) != null){
					evalStr = "parent["+i+"]." + callback+"('"+val+"')";
				}
			}
			if(evalStr!=null){
				eval(evalStr); //去调用父页面 对应的方法
			}
		}
	}

核心方法

eval

<think> 我们需要在父页面调用嵌入的子iframe中定义的函数(方法)。由于浏览器的同源策略限制,如果父子页面不同源,则无法直接访问子iframe的上下文。但如果是同源,或者我们使用了跨域通信技术(如postMessage),就可以实现。 假设父子页面同源,我们可以这样实现: 1. 在父页面中获取到子iframe的引用(即iframe元素)。 2. 通过contentWindow属性获取子窗口的window对象。 3. 然后就可以调用子窗口中的全局函数。 如果不同源,则必须使用postMessage进行通信,子页面需要通过监听message事件来接收命令并执行对应的函数。 下面我将分别给出同源和跨域两种情况的示例。 情况一:同源 父页面(parent.html)代码: 假设子iframe中有一个名为`childFunction`的函数。 父页面中: ```html <!DOCTYPE html> <html> <head> <title>Parent</title> </head> <body> <iframe id="childFrame" src="child.html"></iframe> <script> // 等待iframe加载完成 document.getElementById('childFrame').addEventListener('load', function() { // 获取子窗口的window对象 var childWindow = this.contentWindow; // 调用子窗口中的函数 childWindow.childFunction('Hello from parent!'); }); </script> </body> </html> ``` 子页面(child.html)代码: ```html <!DOCTYPE html> <html> <head> <title>Child</title> </head> <body> <h1>Child Page</h1> <script> // 定义全局函数,供父页面调用 function childFunction(message) { alert('Message in child: ' + message); } </script> </body> </html> ``` 情况二:跨域(使用postMessage) 由于跨域限制,我们无法直接获取子iframe的window对象并调用其函数。因此,我们需要通过postMessage发送消息,子iframe监听消息并执行相应函数。 父页面(parent.html)代码: ```html <!DOCTYPE html> <html> <head> <title>Parent</title> </head> <body> <iframe id="childFrame" src="http://child-domain.com/child.html"></iframe> <script> var childFrame = document.getElementById('childFrame'); childFrame.addEventListener('load', function() { // 发送消息给子iframe // 注意:第二个参数是目标源的URI,可以是具体的URI或'*'(但为了安全不建议使用'*') childFrame.contentWindow.postMessage('Hello from parent!', 'http://child-domain.com'); }); </script> </body> </html> ``` 子页面(child.html)代码: ```html <!DOCTYPE html> <html> <head> <title>Child</title> </head> <body> <h1>Child Page</h1> <script> // 监听父页面发送的消息 window.addEventListener('message', function(event) { // 验证消息来源的域名,避免恶意网站发送的消息 if (event.origin !== 'http://parent-domain.com') { return; } // 执行函数,这里我们用一个函数来处理 processMessage(event.data); }); function processMessage(message) { alert('Message in child: ' + message); // 也可以调用其他函数 } </script> </body> </html> ``` 注意:在跨域的场景中,父页面使用postMessage发送消息时,第二个参数最好指定为子页面的确切源(包括协议、域名和端口),而子页面在接收消息时,一定要校验event.origin,确保消息来自可信的父页面。 以上两种方式分别适用于同源和跨域的情况。 如果问题中的“子iframe外的方法”指的是子iframe中定义的方法,那么以上方法即可解决。 如果问题指的是在子iframe调用父页面方法,那么实际上也是类似的,只是方向相反,这里不再赘述。 下面提出相关问题: </think> ### 父iframe调用iframe内的方法 在Web开发中,父iframe调用iframe内的方法需要遵循以下原则: 1. **同源策略**:父子页面必须在同一域名下(协议/域名/端口一致) 2. **DOM访问**:通过`contentWindow`属性访问子iframe的window对象 3. **加载时机**:确保子iframe加载完成后调用 #### 实现代码: ```html <!-- 父页面 parent.html --> <iframe id="childFrame" src="child.html"></iframe> <script> // 等待子iframe加载完成 document.getElementById('childFrame').addEventListener('load', function() { // 获取子iframe的window对象 const childWindow = this.contentWindow; // 调用iframe中的方法 childWindow.childFunction('参数值'); }); </script> ``` ```html <!-- 子页面 child.html --> <!DOCTYPE html> <html> <head> <title>子页面</title> <script> // 暴露给父页面方法 function childFunction(param) { console.log('来自父页面调用,参数:', param); return '操作成功'; } </script> </head> <body> <!-- 子页面内容 --> </body> </html> ``` #### 关键解释: 1. **contentWindow**: 通过`iframeElement.contentWindow`获取子窗口的全局window对象,这是调用iframe方法的核心 2. **加载事件**: 必须等待`load`事件触发后再调用,确保子iframe已完成初始化 3. **跨域限制**: 如果父子页面不同源,浏览器会阻止访问。解决方法: - 使用postMessage通信 - 设置document.domain(仅适用于相同主域) #### 跨域解决方案(postMessage): ```html <!-- 父页面 --> <script> const iframe = document.getElementById('childFrame'); iframe.addEventListener('load', () => { iframe.contentWindow.postMessage({ action: 'callFunction', params: { data: '重要数据' } }, 'https://子页面域名.com'); }); // 监听子页面响应 window.addEventListener('message', (event) => { if (event.origin !== 'https://子页面域名.com') return; console.log('子页面响应:', event.data); }); </script> <!-- 子页面 --> <script> window.addEventListener('message', (event) => { if (event.origin !== 'https://父页面域名.com') return; if (event.data.action === 'callFunction') { const result = childFunction(event.data.params); // 返回结果给父页面 event.source.postMessage(result, event.origin); } }); </script> ``` #### 安全注意事项: 1. 始终验证`message`事件的`origin`属性 2. 敏感操作需要添加CSRF Token验证 3. 避免在子页面暴露过多全局方法 4. 使用try-catch处理可能的权限异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值