【问题标题】:inject a javascript function into an Iframe将 javascript 函数注入 iframe
【发布时间】:2013-04-18 03:30:38
【问题描述】:

This link (archived version) 描述了如何将脚本中的代码注入 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?)
  • 不知道对不对
  • 我不知道如果函数比这更复杂会发生什么
  • 我不知道scriptFooString 中的双引号和单引号会发生什么情况@

有什么提示吗?

【问题讨论】:

    标签: dom iframe head javascript


    【解决方案1】:

    首先,如果你的框架和显示它的页面在同一个域内,你才能做到这一点(由于跨域规则)

    其次可以通过JS直接操作frame的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());
    

    【讨论】:

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

    【讨论】:

      【解决方案3】:

      这段代码是我研究的结果。接受的答案也对我有很大帮助。 首先,我创建了一个简单的 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;
      

      最后我将js代码注入到iframe中:

      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/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-07
        • 1970-01-01
        • 2012-08-15
        • 2012-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        相关资源
        最近更新 更多