无法重构 JavaScript 中包含 innerHTML 的内联脚本

Unable to refactor inline script contained innerHTML in JavaScript

我目前在JavaScript中有以下代码:

container.innerHTML = `
            <h3 id="box-title"> Build Analysis
             </u><span id="close" class="close" 
            onclick=parentNode.parentNode.style.display='none';>x</span></h3>
             .... /* skipping the rest because it is irrelevant */

这只是在网页中动态插入 HTML 内容的代码(在本例中是可以打开和关闭的框)。我的问题是关于内嵌脚本的。目前它与 onclick 一起工作(关闭 window),但它使用内联脚本,这并不好。

我尝试了这个 link 中的解决方案:(重构内联脚本的部分) https://csp.withgoogle.com/docs/adopting-csp.html

我从那里尝试了以下解决方案,但没有任何反应: 在大多数情况下,更改将很简单。要重构事件处理程序,请重写它们以从 JavaScript 块添加:

从那里复制:

<script> function doThings() { ... } </script>
<span onclick="doThings();">A thing.</span>

应该变成:

<span id="things">A thing.</span>

<script nonce="${nonce}">
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('things')
          .addEventListener('click', function doThings() { ... });
});
</script>

但是在我的项目中应用它时,它似乎不起作用:

 ...
 </u><span id="close" class="close">x</span></h3>
...

<script>
                document.addEventListener('DOMContentLoaded', function () {
                document.getElementById('close')
                        .addEventListener('click', function closeBox() {
                            parentNode.parentNode.style.display='none';
                        });
                });
    </script>

我也试过在标签中放一个 onclick=CloseBox()。它只是没有注册这个功能,什么也没有发生。甚至不会发生错误。有人可以帮忙吗?谢谢!

它不起作用的原因是,当您在 HTML 中有一个 script 标记分配给 innerHTML 时,脚本不是 运行浏览器。

相反,您可以将代码添加到将其分配给 innerHTML:

的代码中
container.innerHTML = `
    <h3 id="box-title"> <u>Build Analysis
     </u><span id="close" class="close">x</span></h3>
     ....`;
document.getElementById('close')
    .addEventListener('click', function closeBox() {
        this.parentNode.parentNode.style.display='none';
    });

另请注意,在第一个 parentNode(在上面添加)和 u 元素(在上面添加)的起始标记之前需要 this.

实例:

var container = document.getElementById("container");
container.innerHTML = `
    <h3 id="box-title"><u> Build Analysis
     </u><span id="close" class="close">x</span></h3>
     ....`;
document.getElementById('close')
    .addEventListener('click', function closeBox() {
        this.parentNode.parentNode.style.display='none';
    });
<div id="container"></div>

如果脚本标记 必须 在被分配的字符串中(例如,因为您从其他地方获取字符串,而不是在您的实际代码中)在你的问题中),你可以在事后获取脚本内容并 运行 它。 innerHTML赋值后:

 container.querySelectorAll("script").forEach(function(script) {
     var newScript = document.createElement("script");
     newScript.textContent = script.textContent;
     document.body.appendChild(newScript); // runs it...
     document.body.removeChild(newScript); // ...after which the `script` element is unnecessary
 });

(您可能需要为旧版浏览器填充 NodeList.prototype.forEach,请参阅 了解如何操作。)

实例:

var container = document.getElementById("container");
container.innerHTML = `
    <h3 id="box-title"><u> Build Analysis
     </u><span id="close" class="close">x</span></h3>
     <script>
     document.getElementById('close')
         .addEventListener('click', function closeBox() {
             this.parentNode.parentNode.style.display='none';
         });
     <\/script>
     ....`;
 container.querySelectorAll("script").forEach(function(script) {
     var newScript = document.createElement("script");
     newScript.textContent = script.textContent;
     document.body.appendChild(newScript); // runs it...
     document.body.removeChild(newScript); // ...after which the `script` element is unnecessary
 });
<div id="container"></div>


旁注:函数中的代码可以通过使用 closest:

变得更加健壮
document.getElementById('close')
    .addEventListener('click', function closeBox() {
        this.closest("h3").style.display='none';
    });