02/5
2016
试想如果我们创建了一个iframe,然后需要访问其中的元素。这时候我们可以对iframe使用onload事件,在其完全载入后执行我们需要的操作。
但是onload事件需要等到图片等资源完全加载完成才执行,这时我想到了jquery的ready()方法,在DOM加载完成后即可执行,更加省时。
但是jquery的ready()方法对框架是无效的。然后我去寻找JavaScript原生的事件,以此来代替jquery的ready()方法。今天终于找到了可行的办法,也是用JavaScript原生的事件做的,实现了和jquery的ready()方法类似的效果。这个代码封装成了函数,我们使用的时候在父窗口调用即可。
代码比较长,我就贴下边了。
这个方法不适用于有跨域问题的情况。下面测试中iframe的url是pixiv上的,可以去pixiv的网页上在控制台执行。
//创建框架 var newFrame=document.createElement("iframe"); newFrame.name="newFrame"; newFrame.id="newFrame"; newFrame.width=300; newFrame.height=300; document.body.appendChild(newFrame); newFrame.src="http://www.pixiv.net/member_illust.php?mode=medium&illust_id=54474518"; //封装ready的函数,框架需要和父窗口同源 function iFrameReady(iFrame, fn) { var timer; var fired = false; function ready() { if (!fired) { fired = true; clearTimeout(timer); fn.call(this); } } function readyState() { if (this.readyState === "complete") { ready.call(this); } } // cross platform event handler for compatibility with older IE versions function addEvent(elem, event, fn) { if (elem.addEventListener) { return elem.addEventListener(event, fn); } else { return elem.attachEvent("on" + event, function () { return fn.call(elem, window.event); }); } } // use iFrame load as a backup - though the other events should occur first addEvent(iFrame, "load", function () { ready.call(iFrame.contentDocument || iFrame.contentWindow.document); }); function checkLoaded() { var doc = iFrame.contentDocument || iFrame.contentWindow.document; // We can tell if there is a dummy document installed because the dummy document // will have an URL that starts with "about:". The real document will not have that URL if (doc.URL.indexOf("about:") !== 0) { if (doc.readyState === "complete") { ready.call(doc); } else { // set event listener for DOMContentLoaded on the new document addEvent(doc, "DOMContentLoaded", ready); addEvent(doc, "readystatechange", readyState); } } else { // still same old original document, so keep looking for content or new document timer = setTimeout(checkLoaded, 1); } } checkLoaded(); } //DOM加载完成即可执行 iFrameReady(document.getElementById("newFrame"), function() { var fonud = this.getElementsByClassName("after")[0].getElementsByTagName("a")[0]; //注意上面的this,this==document.getElementById("newFrame").contentDocument //也可以换种写法 this==window.newFrame.contentDocument console.log(fonud); }); /*参考来源 http://stackoverflow.com/questions/24603580/how-can-i-access-the-dom-elements-within-an-iframe */
调用的时候,两个参数第一个是iframe元素,第二个是函数。调用已有的函数也是可以的。
但是这个方法有个缺点,就是iframe加载完一个页面之后,始终是完成状态,即便你改变了src去加载另一个页面时也是如此。所以当你打算用同一个iframe加载多个页面,并且避免此问题时,可以移除此iframe节点,再重新创建一次。如下:
document.getElementById("iframe1").parentNode.removeChild(document.getElementById("iframe1"));//移除iframe criframe1(nextUrl);// 重新创建iframe1
啊咯哈,新年快乐(⌒▽⌒)