VPN技术 · 2023年11月10日 0

JavaScript操作iframe页面

JavaScript 操作 Iframe 页面

在 JavaScript 中,有两种主要的操作方式:一是在 iframe 内控制外部的 JavaScript 代码,二是在父框架中对 iframe 进行操作。

获取 Iframe 内容

主要的两个 API 是 contentWindowcontentDocument。通过 iframe.contentWindow 可以获取 iframe 的 window 对象,而通过 iframe.contentDocument 可以获取其 document 对象。这两个 API 是 DOM 节点提供的方式。

var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window", iwindow);
console.log("document", idoc);
console.log("html", idoc.documentElement);
console.log("head", idoc.head);
console.log("body", idoc.body);

例如:
JavaScript操作iframe页面

另一种更简单的方法是结合 name 属性,通过 window.frames 来获取。

<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> 

实际上,window.frames['ifr1'] 返回的就是 window 对象,即:

window.frames[ifr1] === window

你可以选择任意一种方式来获取 window 对象,我个人更倾向于使用 frames[xxx],因为它的字符更少。接下来,你就可以操作 iframe 内部的 DOM 内容了。

在 Iframe 中获取父级内容

同样地,在同域下,父页面可以获取子 iframe 的内容,而子 iframe 也能操作父页面内容。在 iframe 中,你可以通过几个挂载在 window 上的 API 来获取数据。

window.parent 获取上一级的 window 对象,如果还是 iframe 则是该 iframe 的 window 对象
window.top 获取最顶层的 window 对象,即打开页面的文档
window.self 返回自身 window 的引用,可以理解为 window === window.self

如图所示:
JavaScript操作iframe页面

一旦获取到这些内容,就可以进行相关操作。在同域的 iframe 中,我们可以利用 iframe 的一些技术实现特定功能。

Iframe 的轮询

早在很久以前,我们通过 iframe 来实现异步请求的发送。为了避免页面跳转,表单提交时也常使用 iframe。随着前端技术的迅速发展,WebSocket、SSE、AJAX 等新技能的出现使得 iframe 的使用逐渐减少,现在主要用于兼容 IE8 及以上版本。因此,了解 iframe 的长轮询和长连接的技巧仍然很重要。

Iframe 长轮询

如果你写过 AJAX,应该知道长轮询的实现方式是在 AJAX 的 readyState = 4 时再次执行原函数。使用 iframe 时同样适用,异步创建 iframe,然后重载,并与后台协商返回的信息,获取其中的数据。示例如下:

var iframeCon = document.querySelector("#container"), text;
var iframe = document.createElement("iframe");
iframe.id = "frame";
iframe.style.display = "none";
iframe.name = "polling";
iframe.src = "target.html";
iframeCon.appendChild(iframe);
iframe.onload = function() {
  var iloc = iframe.contentWindow.location, idoc = iframe.contentDocument;
  setTimeout(function() {
    text = idoc.getElementsByTagName("body")[0].textContent;
    console.log(text);
    iloc.reload(); // 刷新页面以再次获取信息,并触发 onload 函数
  }, 2000);
}

这样就可以实现 AJAX 的长轮询效果。当然,你也可以通过添加或删除 iframe 的方式来发送信息,这取决于具体场景。此外,在 iframe 中还可以实现异步加载 JavaScript 文件,但需要注意的是 iframe 和主页面共享连接池,因此这种方式并不常用。

以下是几种在 iframe 和父页面之间进行交互的示例:

1. 在 iframe 子页面操作父页面元素:

window.parent.document.getElementById("父页面元素id");

2. 在父页面获取 iframe 子页面元素:

window.frames["iframe_ID"].document.getElementById("子页面元素id");

3. 使用 jQuery 在 iframe 子页面获取父页面元素:

$("#objid", parent.document);

4. 使用 jQuery 在父页面获取 iframe 子页面的元素:

$("#objid", document.frames(iframename).document);

5. 在 iframe 中调用父页面定义的方法和变量:

window.parent.window.parentMethod(); window.parent.window.parentValue;

6. 在父页面操作 iframe 子页面的方法和变量:

window.frames["iframe_ID"].window.childMethod(); window.frames["iframe_ID"].window.childValue;

一、同域下父子页面的通信

父页面示例 parent.html

<html>
<head>
    <script type="text/javascript">
        function say() {
            alert("parent.html");
        }
        function callChild() {
            myFrame.window.say();
            myFrame.window.document.getElementById("button").value = "调用结束";
        }
    </script>
</head>
<body>
    <input id="button" type="button" value="调用child.html中的函数say()" onclick="callChild()"/>
    <iframe name="myFrame" src="http://caibaojian.com/child.html"></iframe>
</body>
</html>

子页面示例 child.html

<html>
<head>
    <script type="text/javascript">
        function say() {
            alert("child.html");
        }
        function callParent() {
            parent.say();
            parent.window.document.getElementById("button").value = "调用结束";
        }
    </script>
</head>
<body>
    <input id="button" type="button" value="调用parent.html中的say()函数" onclick="callParent()"/>
</body>
</html>

注意事项

确保在 iframe 加载完成后再进行操作。如果 iframe 尚未加载完成就开始调用内部的方法或变量,将会导致错误。判断 iframe 是否加载完成有两种方法:

1. 使用 iframe 的 onload 事件

2. 使用 document.readyState == "complete" 来判断

二、跨域父子页面通信方法

当 iframe 链接外部页面时,由于安全机制,无法使用同域下的通信方式。

1. 父页面向子页面传递数据

可以利用 location 对象的 hash 值传递数据。在父页面设置 iframe 的 src 后,可以在后面加上 data 字符串,然后在子页面中通过某种方式即时获取这个 data 信息。例如:

1.1 在子页面中通过 setInterval 方法设置定时器,监听 location.href 的变化即可获得 data 信息。

1.2 子页面根据这个 data 信息进行相应的逻辑处理。

2. 子页面向父页面传递数据

可以利用一个代理 iframe,它嵌入到子页面中,并且与父页面同域,通过它利用第一种通信方式的原理,将子页面的数据传递给代理 iframe。由于代理 iframe 和主页面同域,主页面就可以通过同域方式获取这些数据。使用 window.topwindow.parent.parent 获取浏览器最顶层 window 对象的引用。

之前我写过一篇关于 iframe 自适应高度的文章,里面关于 iframe 的操作可以供你参考。

参考链接:http://www.cnblogs.com/sydeveloper/p/3712863.html