公司的项目是 JSP 写的,使用 ifream 的场景非常多。那么 iframe 页面怎么和主页面进行交互呢?
iframe 页面调用主页面的方法
主页面代码
<!DOCTYPE html>
<html>
<script>
function fromFrame(data) {
alert(data);
}
</script>
<body>
<h1>The iframe element</h1>
<iframe name="frame-id" src="./iframe.html" title="Test iframe"></iframe>
</body>
</html>
iframe 页面代码
<!DOCTYPE html>
<html>
<body ">
Enter some text:
<input
type="text"
name="txt"
value="Hello"
onchange="myFunction(this.value)"
/>
<script>
function myFunction(val) {
parent.fromFrame(val);
}
</script>
</body>
</html>
分析
见文档 window.parent
iframe 页面中有这样的代码,其中
parent
返回当前窗口的父窗口对象.
如果一个窗口没有父窗口,则它的 parent
属性为自身的引用.
如果当前窗口是一个 <iframe>
, <object>
, 或者 <frame>
,则它的父窗口是嵌入它的那个窗口
function myFunction(val) {
parent.fromFrame(val);
}
语法
var parentWindow = window.parent;
例子
if (window.parent != window.top) {
// 至少有三层窗口
}
其他
window.frameElement
返回嵌入当前窗口的 frame 对象.
window.top
返回当前窗口最顶层的父窗口.
iframe 页面向主窗口发送信息
主页面
if (window.addEventListener) {
window.addEventListener('message', onMessage, false);
} else if (window.attachEvent) {
window.attachEvent('onmessage', onMessage, false);
}
function onMessage(event) {
// Check sender origin to be trusted
if (event.origin !== 'http://example.com') return;
var data = event.data;
if (typeof window[data.func] == 'function') {
window[data.func].call(null, data.message);
}
}
// Function to be called from iframe
function parentFunc(message) {
alert(message);
}
iframe 页面
window.parent.postMessage(
{
func: 'parentFunc',
message: 'Message text from iframe.',
},
'*'
);
主页面对 ifream 页面进行操作
<!-- 来自同一个网站的 iframe -->
<iframe src="/" id="iframe"></iframe>
<script>
iframe.onload = function() {
// 可以做任何事儿
iframe.contentDocument.body.prepend("Hello, world!");
};
</script>
注意点:如果是跨域的话,是无法进行操作的
<iframe src="https://example.com" id="iframe"></iframe>
<script>
iframe.onload = function() {
// 我们可以获取对内部 window 的引用
let iframeWindow = iframe.contentWindow; // OK
try {
// ...但是无法获取其中的文档
let doc = iframe.contentDocument; // ERROR
} catch(e) {
alert(e); // Security Error(另一个源)
}
// 并且,我们也无法 **读取** iframe 中页面的 URL
try {
// 无法从 location 对象中读取 URL
let href = iframe.contentWindow.location.href; // ERROR
} catch(e) {
alert(e); // Security Error
}
// ...我们可以 **写入** location(所以,在 iframe 中加载了其他内容)!
iframe.contentWindow.location = '/'; // OK
iframe.onload = null; // 清空处理程序,在 location 更改后不要再运行它
};
</script>
主页面与 ifrema 页面的通信
a.com/index.html
<!DOCTYPE html>
<html>
<body>
<script>
let someFunc = (t) => (document.querySelector('#test').text = t);
window.addEventListener('message', (event) => someFunc(e.data));
</script>
<span id="test">This is some dummy text.</span>
<iframe src="https://b.com/index.html"></iframe>
</body>
</html>
b.com/index.html
<!DOCTYPE html>
<html>
<body>
<button id="btn">Test</button>
<script>
document.querySelector('#btn').addEventListener('click', (event) => {
window.parent.postMessage('Changed text', 'http://a.com');
});
</script>
</body>
</html>
主页面调用 iframe 页面的方法
主页面代码
document.getElementById('resultFrame').contentWindow.iframeFunction();
iframe 页面代码
<html>
<head>
<title>iframeFunction</title>
<script type="text/javascript">
function iframeFunction() {
alert('iframeFunction');
}
</script>
</head>
<body>
iframeFunction
</body>
</html>
总结
尽量使用 window.postMessage 方法进行两个页面的通信。