本文已参与「新人创作礼」活动,一起开启掘金创作之路。
iframe常用属性
使用 iframe 通常直接在页面嵌套 iframe 指定 src 即可
<iframe src="demo_iframe_sandbox.htm"></iframe>
iframe 常用属性:
frameborder:是否显示边框,1(yes)、0(no)height:框架作为一个普通元素的高度,建议在使用css设置。width:框架作为一个普通元素的宽度,建议使用css设置。name:框架的名称,window.frames[name]时专用的属性。scrolling:框架的是否滚动。yes、no、auto。src:内框架的地址,可以使页面地址,也可以是图片的地址。srcdoc: 用来替代原来HTML body里面的内容。但是IE不支持, 不过也没什么卵用sandbox:对iframe进行一些列限制,IE10+支持
获取 iframe 内容
iframe.contentWindow
获取 iframe 的 window 对象
document.getElementById("iframe").conetntWindow;
iframe.contentDocument
获取 iframe 的 document 对象
document.getElementById("iframe").contentDocument;
name 属性获取 window 对象
<iframe src="/index.html" id="ifr1" name="ifr1" scrolling="yes">
<p>Your browser does not support iframes.</p>
</iframe>
<script type="text/javascript">
console.log(window.frames["ifr1"].window); // 与下面方式获取等价
console.dir(document.getElementById("ifr1").contentWindow);
</script>
发送消息
对于嵌套iframe的跨域传递消息,一般都采用 postMessage 方法。该方法挂载到目标页面的 window 对象上,即,使用 window.postmessage()调用。
targetWindow.postMessage(message, targetOrigin)
该方法接受两个参数:
message:字符串,不要传 Object 对象,如果要传可以先使用JSON.stringify转成字符串targetOrigin:接受你传递消息的域名,可以设置绝对路径,也可以设置*或者/。*表示任意域名都行,/表示只能传递给同域域名。
接收信息
window.addEventListener('message',fn(event){})
当 targetOrigin 接受到 message 消息之后,会触发 message 事件。 message 提供的 event对象上有 3 个重要的属性,data,origin,source
data:postMessage传递进来的值origin:发送消息的文档所在的域source:发送消息文档的 window 对象的代理,如果是来自同一个域,则该对象就是window,可以使用其所有方法,如果是不同的域,则window只能调用postMessage()方法返回信息
实例
现在有这样一个需求:在一个使用 iframe 多层嵌套的网页最里层中(具体会嵌套多少层不确定,这里只模拟了四级嵌套),创建一个充值按钮点击事件,点击按钮就在第二层页面的 body 节点下新建一个 iframe 用于展示充值页面
要求:
- 必须要在第二层嵌套页面创建
iframe,其他任何嵌套页面创建都不可以; - 只创建或删除
iframe节点,不要操作页面其他任何内容; - 新创建的
iframe节点必须全屏展示,层级要为最高; - 新创建的
iframe节点要能够通过关闭按钮把自己销毁;
要点:
- 多层嵌套的
window对象定位问题 iframe之间的通信问题
第一层页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>h5Iframe</title>
<style>
html,
body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<iframe
src="./2.gameIframe.html"
id="h5Frame"
frameborder="0"
width="100%"
height="100%"
></iframe>
<script>
window.addEventListener("message", function(event) {
console.log(1);
console.log(event);
});
</script>
</body>
</html>
第二层页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>h5Iframe</title>
<style>
html,
body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<iframe
id="gameFrame"
src="./3.iframe.html"
frameborder="0"
width="100%"
height="100%"
></iframe>
<script>
function $(selector) {
return document.querySelector(selector);
}
// 当监听到data=open时,就创建一个充值的iframe
window.addEventListener("message", function(event) {
console.log(2);
if (event.data == "open") {
let iframe = document.createElement("iframe");
iframe.id = "payIframe";
iframe.src = "./index.html";
iframe.setAttribute("frameborder", "0", 0);
iframe.scrolling = "no";
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.position = "fixed";
iframe.style.top = "0";
iframe.style.left = "0";
iframe.style.zIndex = "1000000";
$("body").appendChild(iframe);
} else if (event.data == "close") {
$("#payIframe").remove();
}
});
</script>
</body>
</html>
第三层页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>h5Iframe</title>
<style>
html,
body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<iframe
src="./4.page.html"
id="iframe"
frameborder="0"
width="100%"
height="100%"
></iframe>
<script>
window.addEventListener("message", function(event) {
console.log(3);
console.log(event);
});
</script>
</body>
</html>
第四层页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>h5Iframe</title>
<style>
html,
body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<button id="btn">充值</button>
<script>
function $(selector) {
return document.querySelector(selector);
}
$("#btn").addEventListener("click", function() {
top.document
.getElementById("h5Frame")
.contentWindow.postMessage("open", "*");
// top.frames['h5Frame'].window.postMessage('open', '*'); 与上面方式等价,这是通过name获取节点的window对象
});
// console.log(top.document.getElementById('h5Frame').contentWindow)
</script>
</body>
</html>
充值页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>选择金额</title>
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #f5f5f5;
overflow-y: scroll;
display: flex;
flex-direction: column;
}
.nav {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 18px;
font-weight: 400;
border-bottom: 2px solid #ddd;
position: relative;
}
.nav .close {
width: 50px;
height: 50px;
position: absolute;
right: 0;
top: 0;
color: #aaa;
}
.main {
flex: 1;
}
.main .list {
width: 90%;
padding: 10px;
background: #fff;
border-radius: 10px;
margin: 16px auto;
box-sizing: border-box;
}
.main .list .li {
width: 100%;
height: 40px;
line-height: 40px;
border-bottom: 1px solid #f5f5f5;
display: flex;
justify-content: space-between;
padding: 0 10px;
box-sizing: border-box;
}
.main .list .li .li_detail {
color: #aaa;
font-size: 14px;
}
.main .list .li:last-child {
border-bottom: 0;
}
.main .btn {
display: block;
width: 80%;
background: #ff8500;
margin: 30px auto;
text-align: center;
border: none;
padding: 10px 0;
color: #fff;
border-radius: 6px;
outline: 0;
font-size: 16px;
}
</style>
</head>
<body>
<div class="nav">
<div class="title">充值中心</div>
<div id="close" class="close">X</div>
</div>
<div class="main">
<!-- 信息列表 -->
<div class="list">
<div class="li">
<div class="li_name">购买道具</div>
<div class="li_detail">6000元宝</div>
</div>
<div class="li">
<div class="li_name">道具原价</div>
<div class="li_detail">6.0元</div>
</div>
<div class="li">
<div class="li_name">抵扣券</div>
<div class="li_detail">选择抵扣券</div>
</div>
<div class="li">
<div class="li_name">应付金额</div>
<div class="li_detail">6.0元</div>
</div>
</div>
<!-- 按钮 -->
<button class="btn">确认支付</button>
</div>
<script>
function $(selector) {
return document.querySelector(selector);
}
$("#close").addEventListener("click", function() {
top.document
.getElementById("h5Frame")
.contentWindow.postMessage("close", "*");
});
</script>
</body>
</html>