无法重构 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';
});
我目前在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';
});