将 javascript 函数注入 Iframe

IT技术 dom iframe head javascript
2021-02-12 18:57:05

此链接存档版本)描述了如何将脚本中的代码注入 iframe:

function injectJS() {
  var iFrameHead = window.frames["myiframe"].document.getElementsByTagName("head")[0];
  var myscript = document.createElement('script');
  myscript.type = 'text/javascript';
  myscript.src = 'myscript.js'; // replace this with your SCRIPT
  iFrameHead.appendChild(myscript);
}

没关系,但是如果我想将函数对象插入 iframe并让它在 iframe 上下文中执行怎么办?假设我有:

function foo () {
    console.log ("Look at me, executed inside an iframe!", window);
}

我想在 iframe 中插入 foo 的代码?函数 foo 可能是动态加载的东西,我不能把它用引号括起来

我天真地尝试:

var scriptFooString = "<script>" + foo.toString() + "</script>"

获取函数内部的代码,但是

  • 我不知道如何将它插入 iframe HEAD(也许用 jquery?)
  • 不知道这样对不对
  • 我不知道当 if 函数比那更复杂时会发生什么
  • 我不知道双引号和单引号会发生什么 scriptFooString

任何提示?

3个回答

首先,只有当您的框架和显示它的页面在同一个域中时,您才能完成此操作(由于跨域规则)

其次你可以直接通过JS操作框架的dom和window对象:

frames[0].window.foo = function(){
   console.log ("Look at me, executed inside an iframe!", window);
}

要从 DOMElement 对象中获取您的框架,您可以使用:

var myFrame = document.getElementById('myFrame');

myFrame.contentWindow.foo = function(){
       console.log ("Look at me, executed inside an iframe!");
}

请注意,foo 中的范围没有改变,所以 window 仍然是 foo 中的父窗口等。

如果你想注入一些需要在另一个框架的上下文中运行的代码,你可以注入一个脚本标签,或者对其进行评估:

frames[0].window.eval('function foo(){ console.log("Im in a frame",window); }');

虽然普遍的共识是永远不要使用 eval,但我认为如果你真的需要完成这个,我认为它比 DOM 注入更好。

因此,在您的特定情况下,您可以执行以下操作:

frames[0].window.eval(foo.toString());
我需要在沙箱中执行动态加载的插件(使用 requirejs)。你知道更好的方法吗?
2021-03-17 18:57:05
问题不在于上下文,而在于范围。当你创建函数 foo 时,我相信你在当前范围内创建它,所以 window 是父窗口而不是框架等。你仍然需要使用myFrame.contentWindowframes[0].window在函数内部访问正确的范围。如果你需要注入一个脚本标签,你可以通过 DOM 附加它。
2021-03-20 18:57:05
我已经更新了我的答案以更好地匹配您的查询。虽然我必须说,如果你需要做这样的事情,很可能你把事情复杂化了,你做错了,或者可能做得更聪明。
2021-03-25 18:57:05
好的,但是如果我从父窗口执行函数frames[0].window.foo();,它会在父窗口上下文中执行。将它插入头部会使其与 iframe 上下文一起执行,我错了吗?(见jsfiddle.net/7rEXT
2021-04-03 18:57:05

这段代码是我研究的结果。接受的答案也对我有很大帮助。首先,我创建了一个简单的 iframe:

<iframe id="myiframe" width="200" height="200" srcdoc="<h1 id='title'>Hello from Iframe</h1><button type='button' id='fire'>Click Me!</button>
"></iframe>

为了访问 iframe 的窗口和文档,我使用了此代码。

const iframe = document.getElementById('myiframe');
const iframeWin = iframe.contentWindow || iframe;
const iframeDoc = iframe.contentDocument || iframeWin.document;

最后我在 iframe 中注入了 js 代码:

var script = iframeDoc.createElement("script");
  script.append(`
    window.onload = function() {
     document.getElementById("fire").addEventListener('click', function() {
        const text = document.getElementById('title').innerText;
        alert(text);
     })
  }
`);
  iframeDoc.documentElement.appendChild(script);

演示: https : //jsfiddle.net/aliam/1z8f7awk/2/

这是我的解决方案。我使用 jquery 插入内容,然后使用 eval 在该 iframe 的上下文中执行脚本标记:

    var content = $($.parseHTML(source, document, true));
    $("#content").contents().find("html").html(content);
    var cw = document.getElementById("content").contentWindow;
    [].forEach.call(cw.document.querySelectorAll("script"), function (el, idx) {
        cw.eval(el.textContent);
    });