我在我的HTML页面中加载一个<iframe>,并试图使用JavaScript访问其中的元素,但当我尝试执行我的代码时,我得到以下错误:

阻止原点为“http://www.example.com”的帧访问跨原点帧。

如何访问框架中的元素?

我正在使用这段代码进行测试,但徒劳:

$(document).ready(function() {
    var iframeWindow = document.getElementById("my-iframe-id").contentWindow;

    iframeWindow.addEventListener("load", function() {
        var doc = iframe.contentDocument || iframe.contentWindow.document;
        var target = doc.getElementById("my-target-id");

        target.innerHTML = "Found it!";
    });
});

当前回答

如果你可以控制iframe的内容——也就是说,如果它只是在一个跨起源的设置中加载,比如在Amazon Mechanical Turk上——你可以用<body onload='my_func(my_arg)'>属性来规避这个问题。

例如,对于内部html,使用this html参数(yes -这是定义的,它引用内部主体元素的父窗口):

<身体onload = ' changeForm(这)>

在内部html:

    function changeForm(window) {
        console.log('inner window loaded: do whatever you want with the inner html');
        window.document.getElementById('mturk_form').style.display = 'none';
    </script>

其他回答

补充Marco Bonelli的回答:当前框架/iframe之间的最佳交互方式是使用窗口。所有浏览器都支持的postMessage

实际上,在特定的情况下,有一个变通办法。

如果在同一个域上运行两个进程,但端口不同,那么两个Windows可以不受限制地交互。(即localhost:3000 & localhost:2000)。为了实现这一点,每个窗口都需要将它们的域更改为共享源:

document.domain = 'localhost'

这也适用于您正在使用同一二级域上的不同子域的场景,即您在john.site.example上试图访问peter.site.example或只是site.example

document.domain = 'site.example'

通过显式设置document.domain;浏览器将忽略主机名的差异,Windows可以被视为来自“同源”。现在,在父窗口中,你可以进入iframe:

打开开始菜单 输入windows+R或打开“运行” 执行如下命令。

Chrome .exe——user-data-dir="C://Chrome dev session"——disable-web-security .exe

当我试图嵌入一个iframe,然后用Brave打开网站时,我遇到了这个错误。当我把这个网站改为“盾牌下降”时,这个错误就消失了。显然,这并不是一个完整的解决方案,因为任何使用Brave访问网站的人都会遇到同样的问题。要真正解决这个问题,我需要做本页上列出的其他事情之一。但至少我现在知道问题出在哪里了。

对我来说,我想实现一个双向握手,这意味着: 父窗口的加载速度比iframe快 iframe应该在准备好后立即与父窗口对话 -父节点已经准备好接收iframe消息并重播

此代码用于在iframe中使用[CSS自定义属性]设置白色标签 代码: iframe

$(function() {
    window.onload = function() {
        // create listener
        function receiveMessage(e) {
            document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
            document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
            document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
            //alert(e.data.data.header_bg);
        }
        window.addEventListener('message', receiveMessage);
        // call parent
        parent.postMessage("GetWhiteLabel","*");
    }
});

$(function() {
    // create listener
    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
    var eventer = window[eventMethod];
    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
    eventer(messageEvent, function (e) {
        // replay to child (iframe) 
        document.getElementById('wrapper-iframe').contentWindow.postMessage(
            {
                event_id: 'white_label_message',
                wl: {
                    header_bg: $('#Header').css('background-color'),
                    header_text: $('#Header .HoverMenu a').css('color'),
                    button_bg: $('#Header .HoverMenu a').css('background-color')
                }
            },
            '*'
        );
    }, false);
});

当然,您可以限制起源和文本,这很容易与代码一起工作 我发现下面这个例子很有帮助: [使用postMessage的跨域消息传递]