我想从iframe调用父窗口JavaScript函数。

<script>
    function abc()
    {
        alert("sss");
    }
</script>

<iframe id="myFrame">
    <a onclick="abc();" href="#">Call Me</a>
</iframe>

当前回答

Ash Clarke为子域名提供的解决方案很好,但请注意,您需要包括文档。域名= "mydomain.com";在iframe页眉和父页眉中,如链接同源策略检查中所述

An important extension to the same origin policy implemented for JavaScript DOM access (but not for most of the other flavors of same-origin checks) is that two sites sharing a common top-level domain may opt to communicate despite failing the "same host" check by mutually setting their respective document.domain DOM property to the same qualified, right-hand fragment of their current host name. For example, if http://en.example.com/ and http://fr.example.com/ both set document.domain to "example.com", they would be from that point on considered same-origin for the purpose of DOM manipulation.

其他回答

Ash Clarke为子域名提供的解决方案很好,但请注意,您需要包括文档。域名= "mydomain.com";在iframe页眉和父页眉中,如链接同源策略检查中所述

An important extension to the same origin policy implemented for JavaScript DOM access (but not for most of the other flavors of same-origin checks) is that two sites sharing a common top-level domain may opt to communicate despite failing the "same host" check by mutually setting their respective document.domain DOM property to the same qualified, right-hand fragment of their current host name. For example, if http://en.example.com/ and http://fr.example.com/ both set document.domain to "example.com", they would be from that point on considered same-origin for the purpose of DOM manipulation.

虽然其中一些解决方案可能有效,但没有一个符合最佳实践。许多分配全局变量,您可能会发现自己调用多个父变量或函数,导致混乱、易受攻击的命名空间。

为了避免这种情况,可以使用模块模式。在父窗口:

var myThing = {
    var i = 0;
    myFunction : function () {
        // do something
    }
};

var newThing = Object.create(myThing);

然后,在iframe中:

function myIframeFunction () {
    parent.myThing.myFunction();
    alert(parent.myThing.i);
};

这类似于Crockford的开创性文本“Javascript: the Good Parts”的继承章节中描述的模式。你也可以在w3的页面上了解更多Javascript的最佳实践。https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals

Window.postMessage ()

这种方法可以安全地实现跨源通信。

如果你可以访问父页代码,那么任何父方法都可以被调用,任何数据都可以直接从Iframe中传递。这里有一个小例子:

父页面:

if (window.addEventListener) {
    window.addEventListener("message", onMessage, false);        
} 
else if (window.attachEvent) {
    window.attachEvent("onmessage", onMessage, false);
}

function onMessage(event) {
    // Check sender origin to be trusted
    if (event.origin !== "http://example.com") return;

    var data = event.data;

    if (typeof(window[data.func]) == "function") {
        window[data.func].call(null, data.message);
    }
}

// Function to be called from iframe
function parentFunc(message) {
    alert(message);
}

Iframe代码:

window.parent.postMessage({
    'func': 'parentFunc',
    'message': 'Message text from iframe.'
}, "*");
// Use target origin instead of *

更新:

安全注意事项:

如果您知道其他窗口的文档应该位于何处,则始终提供特定的targetOrigin,而不是*。未能提供特定的目标会泄露你发送到任何感兴趣的恶意网站的数据(由ZalemCitizen评论)。

引用:

跨文档信息 Window.postMessage () 我可以用

我把这个作为一个单独的答案,因为它与我现有的答案无关。

这个问题最近在从引用子域的iframe访问父节点时再次出现,现有的修复不起作用。

这一次的答案是修改文件。父页面的域和iframe必须相同。这将使同源策略检查误以为它们共存于完全相同的域中(子域被视为不同的主机,同源策略检查失败)。

将以下内容插入到iframe中页面的<head>以匹配父域(根据您的doctype进行调整)。

<script>
    document.domain = "mydomain.com";
</script>

请注意,这将在本地主机开发时抛出一个错误,所以使用如下检查来避免错误:

if (!window.location.href.match(/localhost/gi)) {
    document.domain = "mydomain.com";
} 

出于安全考虑,Parent.abc()只能在同一域上工作。我试过这个方法,我的效果很好。

<head>
    <script>
    function abc() {
        alert("sss");
    }

    // window of the iframe
    var innerWindow = document.getElementById('myFrame').contentWindow;
    innerWindow.abc= abc;

    </script>
</head>
<body>
    <iframe id="myFrame">
        <a onclick="abc();" href="#">Click Me</a>
    </iframe>
</body>

希望这能有所帮助。:)