参考文献:
a 标签onclick 和 href冲突
frame VS iframe
w3c已经不推荐使用frame
,而推荐使用iframe
,iframe
也就是inline frame
(行内frame),顾名思义它具有css
的行内框特性,正是因为这一特性才引出来iframe
高度100%时,出现垂直滚动条。
frame相关window属性
window.frames
window.frames
属性返回一个类似数组的对象,成员为页面内所有框架窗口,包括frame
元素和iframe
元素。window.frames[0]
表示页面中第一个框架窗口。
如果iframe
元素设置了id
或name
属性,那么就可以用属性值,引用这个iframe
窗口。比如<iframe name="myIFrame">
可以用frames['myIFrame']
或者frames.myIFrame
来引用。
frames
属性实际上是window
对象的别名。
js
frames === window // true
因此,frames[0]
也可以用window[0]
表示。但是,从语义上看,frames
更清晰,而且考虑到window
还是全局对象,因此推荐表示多窗口时,总是使用frames[0]
的写法。
window.length
window.length
属性返回当前网页包含的框架总数。如果当前网页不包含frame
和iframe
元素,那么window.length
就返回0
。
js
window.frames.length === window.length // true
上面代码表示,window.frames.length
与window.length
应该是相等的。
window.frameElement
window.frameElement
属性主要用于当前窗口嵌在另一个网页的情况(嵌入<object>
、<iframe>
或<embed>
元素),返回当前窗口所在的那个元素节点 。如果当前窗口是顶层窗口,或者所嵌入的那个网页不是同源的,该属性返回null
。
js
// HTML 代码如下
// <iframe src="about.html"></iframe>
// 下面的脚本在 about.html 里面
var frameEl = window.frameElement;
if (frameEl) {
frameEl.src = 'other.html';
}
上面代码中,frameEl
变量就是<iframe>
元素。
iframe相关获取
通过window获取iframe
window.frames是个伪数组,可以通过window.frames[index]
或window.frames[name]
来获取iframe
window.frames[index]
,索引是从左往右,从上往下的,从0开始,- 通常我们使用
window.frames[name]
来获取iframe
通过iframe获取window、document
如果想获取iframe里的window或者document,可以使用
iframe.contentWindow
iframe.contentDocument
iframe.contentDocument
=iframe.contentWindow.document
,不过iframe.contentDocument
在IE8及以下的版本不支持。
如何调用iframe中的方法
如果想调用iframe中的方法,可以按照以下步骤:
(1)在父页面中获取iframe
元素的引用
js
let iframe = document.getElementById('iframeId')
(2)通过iframe
的contentWindow
属性获取到iframe
中的window
对象
js
let iframeWindow = iframe.contentWindow
(3)接着就可以调用iframe中定义的方法了
js
iframeWindow.methodName()
调用跨域iframe中的方法需要在两个页面之间建立信任关系,具体可以参考跨域通信相关知识。
多窗口操作
由于网页可以使用iframe
元素,嵌入其他网页,因此一个网页之中会形成多个窗口。如果子窗口之中又嵌入别的网页,就会形成多级窗口。
窗口的引用
各个窗口之中的脚本,可以引用其他窗口。浏览器提供了一些特殊变量,用来返回其他窗口。
top
:顶层窗口,即最上层的那个窗口parent
:父窗口self
:当前窗口,即自身
下面代码可以判断,当前窗口是否为顶层窗口。
js
if (window.top === window.self) {
// 当前窗口是顶层窗口
} else {
// 当前窗口是子窗口
}
下面的代码让父窗口的访问历史后退一次
js
window.parent.history.back();
与这些变量对应,浏览器还提供一些特殊的窗口名,供window.open()
方法、<a>
标签、<form>
标签等引用。
_top
:顶层窗口_parent
:父窗口_blank
:新窗口
下面代码就表示在顶层窗口打开链接。
html
<a href="somepage.html" target="_top">Link</a>
iframe元素
对于iframe
嵌入的窗口,document.getElementById
方法可以拿到该窗口的 DOM 节点,然后使用contentWindow
属性获得iframe
节点包含的window
对象。
js
var frame = document.getElementById('theFrame');
var frameWindow = frame.contentWindow;
上面代码中,frame.contentWindow
可以拿到子窗口的window
对象。然后,在满足同源限制的情况下,可以读取子窗口内部的属性。
js
// 获取子窗口的标题
frameWindow.title
<iframe>
元素的contentDocument
属性,可以拿到子窗口的document
对象。
js
var frame = document.getElementById('theFrame');
var frameDoc = frame.contentDocument;
// 等同于
var frameDoc = frame.contentWindow.document;
<iframe>
元素遵守同源政策,只有当父窗口与子窗口在同一个域时,两者之间才可以用脚本通信,否则只有使用window.postMessage
方法。
<iframe>
窗口内部,使用window.parent
引用父窗口。如果当前页面没有父窗口,则window.parent
属性返回自身。
因此,可以通过window.parent
是否等于window.self
,判断当前窗口是否为iframe
窗口。
javascript
if (window.parent !== window.self) {
// 当前窗口是子窗口
}
<iframe>
窗口的window
对象,有一个frameElement
属性,返回<iframe>
在父窗口中的 DOM 节点。对于非嵌入的窗口,该属性等于null
。
ini
var f1Element = document.getElementById('f1');
var f1Window = f1Element.contentWindow;
f1Window.frameElement === f1Element // true
window.frameElement === null // true
window.frames属性进一步说明
window.frames
属性返回一个类似数组的对象,成员是所有子窗口的window
对象。可以使用这个属性,实现窗口之间的互相引用。比如,frames[0]
返回第一个子窗口,frames[1].frames[2]
返回第二个子窗口内部的第三个子窗口,parent.frames[1]
返回父窗口的第二个子窗口。
js
// renderTableData为绑定在iframe窗口的window上的方法
if (window.frames?.[iframeName]?.renderTableData) {
window.frames[iframeName].renderTableData();
}
注意,
window.frames
每个成员的值,是框架内的窗口(即框架的window
对象),而不是iframe
标签在父窗口的 DOM 节点。如果要获取每个框架内部的 DOM 树,需要使用window.frames[0].document
的写法。
另外,如果<iframe>
元素设置了name
或id
属性,那么属性值会自动成为全局变量,并且可以通过window.frames
属性引用,返回子窗口的window
对象。
ini
// HTML 代码为 <iframe id="myFrame">
window.myFrame // [HTMLIFrameElement]
frames.myframe === myFrame // true
另外,name
属性的值会自动成为子窗口的名称,可以用在window.open
方法的第二个参数,或者<a>
和<frame>
标签的target
属性。
window获取顶级窗口、父窗口
- 获取顶级窗口:
window.top
- 获取父级窗口:
window.parent
- 导航栏回退:
history.back()
; 注意回退的请求,会有缓存。 - 前进:
history.forward()
history.back()和history.forward()仅仅是为了方便分别代替history.go(-1)和history.go(1)