如何在JavaScript中在窗口和框架之间共享数据

How to share a data between a window and a frame in JavaScript

本文关键字:框架 之间 共享 数据 窗口 JavaScript      更新时间:2023-09-26

这是WebKit浏览器特定的(这意味着我只需要使它在WebKit特定的工作,即iOS/Android浏览器,但我在Chrome测试)。

我有一个页面。页面加载一个或多个iframe,其中包含来自另一个域的内容。我需要接收来自这些iframe的消息(使用postMessage()),并且我需要能够识别特定消息来自哪个iframe。

我找不到一种方法来做到这一点,不涉及抛出一些iframe URL, iframe内容然后可以传递给我。我希望不必干预URL,因为不能保证我可以安全地这样做(例如,重定向可能会抛出参数)。

我尝试了一些我认为合理的事情。当我创建iframe元素时(这是从J/S中完成的),我将一个属性与元素关联起来,我们说'shared_secret'。当我从框架中获得消息事件返回时,我尝试找到创建调用框架的元素,并读取该属性。

function onMessage(evt) {
  var callerId = evt.source.frameElement.shared_secret;
  // ....
}
window.addEventListener(message, onMessage);
var frameEl = document.createElement('iframe');
frameEl.shared_secret = 'sommething blue';
frameEl.src = 'http://aliens.com/my.html';
somewhereInMyDoc.appendChild(frameEl);

当帧加载时,它将运行:

window.parent.postMessage('do you know who I am?', '*');

但是,在上面的onMessage()中frameElement是未定义的。我想出于安全原因,当父/子节点来自同一域时,它确实工作得很好。

这其实很讽刺。父窗口不能访问event.source. frameelement,因为event。来源是外星人的窗口。iFrame窗口不能调用window.frameElement,因为frameElement在一个外部窗口中。所以没有人可以访问它。

那么,有没有什么东西我可以用作令牌,我可以在新加载的帧上设置,并以某种方式取回?

谢谢。

对于寻找一些代码的人,下面是我用来查找发送消息的iframe的代码:

/**
 * Returns the iframe corresponding to a message event or null if not found.
 * 
 * 'e' is the event object
 */
function getFrameTarget (e) {
    var frames = document.getElementsByTagName('iframe'),
        frameId = 0,
        framesLength = frames.length;
    for (; frameId < framesLength; frameId++) {
        if (frames[frameId].contentWindow === e.source) {
            return frames[frameId];
        }
    }
    return null;
}

感谢Pawel Veselov和DMoses !

这应该归功于https://stackoverflow.com/users/695461/dmoses。

可以将frame元素的内容窗口对象与事件进行比较。消息事件的源,如果它们实际上相同,则比较将产生TRUE。

因此,为了解决我的特殊问题,我需要保留我创建的框架元素列表(如果需要,使用任何附加属性点缀它们),并且当事件进入时,遍历所有元素,寻找具有其contentWindow属性等于事件的元素。源属性。

我们做了,通过遇到一些讨厌的bug,也发现你应该在父窗口内创建的iframe上放一个'id'。特别是如果窗口本身在iframe中。否则,某些(Android 4)。即使消息是从一个完全不同的子框架接收的,也会产生真正的比较。