在 iframe 中添加一个脚本标签,其内容由 srcdoc 设置

Posted

技术标签:

【中文标题】在 iframe 中添加一个脚本标签,其内容由 srcdoc 设置【英文标题】:add an script tag in iframe whose content is getting set by srcdoc 【发布时间】:2021-01-21 03:15:23 【问题描述】:

所以我想做的是这样的 - 假设我有一个这样的 htmlString --

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    </script>
  </body>
</html>`

我想修改这个字符串并添加一个--另一个脚本标签作为--第一个脚本标签--得到输出字符串--

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="">console.log("Script Added at top")</script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    </script>
  </body>
</html>`

不知道head标签里面还有多少其他标签,所以不能做简单的查找和替换

【问题讨论】:

【参考方案1】:

DOME 操作可以工作,但您永远无法将脚本作为第一个要执行的脚本插入:

注意:这在 stacksn-p 中不起作用 - 请在您自己的服务器上尝试

const html = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`
const script = document.createElement("script");
script.textContent = `console.log("Script Added at top")`;
const iframe = document.createElement("iframe");
iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);
document.body.appendChild(iframe);
const doc = iframe.contentWindow;
doc.querySelector("head").appendChild(script);

如果脚本是外部的,您可以从 /script 中删除 \

let html = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`.split("\n")
html.splice(4,0,`    <script src="">console.log("Script Added at top")<\/script>`)
const htmlString = html.join("\n")
console.log(htmlString)

在任何脚本之前插入:

let htmlString = `<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"><\/script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"><\/script>
  </head>
  <body>
            <img src="https://images.unsplash.com/photo-1593642532744-d377ab507dc8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80"/>
    <div id="root"></div>
    <script type="text/jsx">
      ReactDOM.render(
        <h1>Hello, React!</h1>,
        document.getElementById('root')
      );
    <\/script>
  </body>
</html>`
parts = htmlString.split("<script")
parts[0] += `    <script src="">console.log("Script Added at top")<\/script>\n     `;
htmlString = parts.join("<script")
console.log(htmlString)

【讨论】:

感谢您的回答,但问题是我不能在 "\n" 上拆分,因为一行中可能有多个标签,我不知道里面还有多少其他标签头部标签。 查看第二个版本 如果你知道标题总是在任何脚本之前,你也可以在标题之后插入 再次感谢,但正如我所说的那样,所有这些问题是 -- 标题 -- 可能不存在,脚本可能不存在,第一个脚本可能写成 -- " 如果您想首先进行 DOM 操作,您不能在其他脚本运行之前插入和运行您的脚本。如果你不介意排在最后,你当然可以做 DOM 操作

以上是关于在 iframe 中添加一个脚本标签,其内容由 srcdoc 设置的主要内容,如果未能解决你的问题,请参考以下文章

在网页上的所有 iframe 中注入 iframe 的内容脚本

在 iFrame 中激活 Zurb Foundation 的 Joyride,来自 Chrome 扩展内容脚本

怎么让iframe自适应浏览器的高度和宽度

跨域 iframe 调整大小?

可以在A标签中嵌入iFrame并使悬停/链接有效吗?

如何在我的扩展程序的新标签页中将其他扩展程序的新标签页加载为 iFrame