关于frames的笔记

最近工作需求需要,用到了iframe,由于页面之间没有跨域,所以js写起来还算顺畅,不过在给同事讲postMessage的使用时,遇到了一个使用问题,导致自己以为子页面iframe之间不能通过postMessage通信,只能通过子A传父,父再传子B的形式来实现A和B通信,然而静下心来发现,其实是自己用错了方式。

遇到的问题

iframe其实是个很棒的技术支持,详见».

起初遇到的问题是,一个页面里有两个iframe(A和B),通过postMessage的使用方式:

	// A.html
	window.top.frames['frame1'].postMessage({data:1}, "*");

结果页面报跨域错误(几个页面不在同一个域上),当时也纳闷,postMessage不是支持跨域么?

而后,改成

	// A.html
	window.top.frames[0].postMessage({data:1}, "*");

居然就可以了。当时直接就打印一下frames[id]frames[index],发现不是同一个内容,前一个返回的是,iframe元素DOM,而后者则是返回iframe的window。

所以这是怎么回事呢?

window.frames

既然说到了一个知识点概念,那么就要祭出MDN文档了.

文档中提及的window.frames主要有三个特点:

  1. 它是一个frame对象的列表类数组对象,具有length属性表示frame个数,以及可以通过下标方式访问到frame
  2. 它总是全等于当前window对象(注意点)
  3. 它以下标访问的数组元素,表示<frame><iframe>的内容,而不是标签DOM元素,即相当于document.getElementsByTagName( "iframe" )[ 0 ].contentWindow

留意后两点,当我们用frames[index]得到的是frame页面的window对象,而当我们用frames[id]的方式,实际上访问的是当前window对象的id对应的属性,这是个啥呢?

可以查看这里描述, 当给dom赋值id之后,可通过window[id]的方式直接访问到dom,于是frames[id]就访问到了当前window里的id对应的dom,也就是iframe DOM。

window.frameElement

关于这个属性,是我遇到的另一个问题,就是我只知道当前页面A是以iframe的形式嵌入父页面B,我想在iframe的js里将自己作为iframe的DOM添加allowfullscreen属性,于是就想着用window.parent.frames得到父页面所有的frame,然后遍历匹配每个frame和自己当前的frame的location进行比较,但总觉得这是个比较多余的操作,总觉得应该有一个api直接就能得到当前iframe在父页面的标签DOM。(遍历的时候遇到的一个问题是,有一个iframe是空白页,结果在firefox下抛异常了,于是还得捕获异常)

而这个属性,就是这么个意思,又要祭出MDN文档,返回嵌入当前window对象的元素,当页面是顶层页面或者父子页面之前存在跨域时,返回null。

这要不是在工作中运用遇到问题,估计很长一段时间保持的原来的无知状态(以前用iframe都没涉及到这块内容)。想想正好月初,把这两点记下来交任务了~