为啥浏览器不在通过 fetch API 检索的 HTML 片段中运行 <script>? [复制]

Posted

技术标签:

【中文标题】为啥浏览器不在通过 fetch API 检索的 HTML 片段中运行 <script>? [复制]【英文标题】:Why doesn't a browser run a <script> in an HTML fragment retrieved via fetch API? [duplicate]为什么浏览器不在通过 fetch API 检索的 HTML 片段中运行 <script>? [复制] 【发布时间】:2018-09-26 18:38:48 【问题描述】:

我正在尝试使用 fetch API 获取 html 片段,然后将其添加到 HTML 页面。虽然这适用于 HTML 内容,但我注意到如果我在片段中放置 &lt;script&gt; 标记,该标记不会被剥离,但也不会被执行。

下面是一个例子。我希望alert 会触发,但它不会触发,即使脚本标签出现在页面上。

我的问题是 (1) 为什么 &lt;script&gt; 没有得到评估,以及 (2) 有没有办法让它评估?

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Index</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>

fragment.html

<h1>Hello</h1>
<p>It works</p>
<script>
  alert('hello') // doesn't work, but script still appears on page
</script>

main.js

fetch('fragment.html').then((res)=>
  return res.text()
).then((data)=>
  var div = document.createElement('div')
  div.innerHTML = data
  document.body.appendChild(div)
)

【问题讨论】:

因为脚本只在加载页面时执行。 您可以使用$(elm).html(str) 而不是elm.innerHTML=str; 来运行此类内容。 【参考方案1】:

因为这就是HTML spec dictates:

使用innerHTML 插入的脚本元素在被插入时不会执行 插入。

我在这里做一些假设,但可能是为了引入一层安全性,这样你就不会意外引入 XSS 或code injection。


如果你想让脚本运行,获取它们的内容,创建一个特定的&lt;script&gt; 元素,将脚本的主体设置为内容,然后将其插入到 DOM 中:

const script = document.createElement("script"),
  text = document.createTextNode("console.log('foo')");

script.appendChild(text);
document.body.appendChild(script);

【讨论】:

以上是关于为啥浏览器不在通过 fetch API 检索的 HTML 片段中运行 <script>? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Fetch API 调用不返回响应标头?

通过 Node-Fetch 检索 OAuth2 令牌

Javascript fetch api:无法检索某些响应标头

从 fetch 中检索数据 [关闭]

如何使用 Fetch API 从表单中检索和发送数据?

如何使用我使用 fetch API 调用检索到的数据更新 Reactjs 状态?