简体   繁体   English

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

[英]Unable to refactor inline script contained innerHTML in JavaScript

I currently have the following code 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 */

This is just code for dynamically inserting HTML content in the webpage (in this case box that can be opened and closed).这只是在网页中动态插入 HTML 内容的代码(在这种情况下是可以打开和关闭的框)。 My question is regarding in-line scripting.我的问题是关于内联脚本。 Currently it works with the onclick (which closes the window), but it uses inline scripting, which is not good.目前它适用于onclick (关闭窗口),但它使用内联脚本,这并不好。

I tried the solutions from this link:(the part with refactoring in-line scripting) https://csp.withgoogle.com/docs/adopting-csp.html我从这个链接尝试了解决方案:(重构内联脚本的部分) https://csp.withgoogle.com/docs/adopting-csp.html

I tried the following solution from there, but nothing happens: In most cases the changes will be straightforward.我从那里尝试了以下解决方案,但没有任何反应:在大多数情况下,更改将很简单。 To refactor event handlers, rewrite them to be added from a JavaScript block:要重构事件处理程序,请将它们重写为从 JavaScript 块添加:

Copied from there:从那里复制:

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

should become:应该变成:

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

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

However when applying it my project, it doesnt seem to work:但是,在我的项目中应用它时,它似乎不起作用:

 ...
 </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>

I also tried putting a onclick=CloseBox() in the tag.我还尝试在标签中放置一个onclick=CloseBox() It just doesn't register this functionality and nothing happens.它只是没有注册此功能并且没有任何反应。 Not even an error occurs.甚至没有发生错误。 Can anyone please help?有人可以帮忙吗? Thank you!谢谢!

The reason it doesn't work is that when you have a script tag in HTML that you assign to innerHTML , the script is not run by the browser.它不起作用的原因是,当您在 HTML 中有一个分配给innerHTMLscript标记时,该脚本不会由浏览器运行。

Instead, you would add your code to the code that's assigning this to 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';
    });

Also note that you need this.另请注意,您需要this. before the first parentNode (added above) and the starting tag for the u element (added above).在第一个parentNode (上面添加)和u元素的起始标记(上面添加)之前。

Live Example:现场示例:

 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>

If the script tag has to be in the string being assigned (for instance, because you get the string from somewhere else, rather than it being in your actual code as it is in your question), you can get the script content after the fact and run it.如果脚本标签必须在分配的字符串中(例如,因为您从其他地方获取字符串,而不是在您的问题中的实际代码中),您可以在事后获取脚本内容并运行它。 After the innerHTML assignment: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
 });

(You may need to polyfill NodeList.prototype.forEach for older browsers, see my answer here for how to do that.) (您可能需要为较旧的浏览器填充NodeList.prototype.forEach ,请参阅我的答案here了解如何做到这一点。)

Live Example:现场示例:

 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>


Side note: The code in the function could be made more robust by using closest :旁注:使用closest的代码可以使 function 中的代码更加健壮:

document.getElementById('close')
    .addEventListener('click', function closeBox() {
        this.closest("h3").style.display='none';
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM