使用纯 javascript 遍历所有 iframe 并更改它们的 CSS 样式
Looping through all iframes with plain javascript and altering their CSS styles
我有一个父 HTML 文件,其中包含托管在同一域中的多个 iframe。现在我想遍历所有 iframe 并通过向它们添加 CSS 带有纯 javascript 样式来更改它们的视觉外观:
<!DOCTYPE html>
<html>
<head>
<title>
Altering CSS in iframe
</title>
</head>
<body>
<h1>Parent HTML</h1>
<iframe id="frameID1" name="frameID1" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #1</p>
</body>
</html>
"></iframe>
<iframe id="frameID2" name="frameID2" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #2</p>
</body>
</html>
"></iframe>
<iframe id="frameID3" name="frameID3" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #3</p>
</body>
</html>
"></iframe>
<script>
var iframes = document.getElementsByTagName("iframe");
for (var i = 0; i < iframes.length; i++) {
iframes.item(i).addEventListener("load", function() {
var node = document.createElement('style');
node.appendChild(document.createTextNode('body { background: red; }'));
window.frames[i].document.head.appendChild(node)
})
}
</script>
</body>
</html>
但是 javascript 代码中的循环不起作用。我已经设置了一个 fiddle,其中我将 window.frames[i].document.head.appendChild(node)
更改为 window.frames[i-2].document.head.appendChild(node)
这显示了一种效果,但仅更改了一个 iframe 中的样式,而不是所有 iframe 中的样式:
https://jsfiddle.net/5a8bdynm/
我必须更改什么才能影响所有 iframe?
您正在使用 var
在 for
循环中定义索引 i。所以,你的索引是一个全局变量。
但是您的事件(加载)是异步的 (1),因此当第一个 iframe 加载时,索引的值已经是 3。在这种情况下,window.frames[i]
将始终引用 window.frames[3]
甚至不存在。
如果将 var
替换为 let
,每个循环周期将收到其自己单独的索引值,并且 window.frames[i]
将引用正确的 iframe。
const iframes = document.getElementsByTagName("iframe")
for (let i = 0; i < iframes.length; i++) { // your code}
一般来说,您应该避免使用 var
。
首选 let
和 const
作为最佳实践。
(1) 编辑: 顺便说一句,加载事件的异步性质在这种情况下并不相关,因为代码是事件处理程序的一部分;所以,无论事件是什么,它都会在循环结束后执行(然后,在全局索引变量的值为 3 后)
我有一个父 HTML 文件,其中包含托管在同一域中的多个 iframe。现在我想遍历所有 iframe 并通过向它们添加 CSS 带有纯 javascript 样式来更改它们的视觉外观:
<!DOCTYPE html>
<html>
<head>
<title>
Altering CSS in iframe
</title>
</head>
<body>
<h1>Parent HTML</h1>
<iframe id="frameID1" name="frameID1" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #1</p>
</body>
</html>
"></iframe>
<iframe id="frameID2" name="frameID2" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #2</p>
</body>
</html>
"></iframe>
<iframe id="frameID3" name="frameID3" srcdoc="
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>This is my iframe #3</p>
</body>
</html>
"></iframe>
<script>
var iframes = document.getElementsByTagName("iframe");
for (var i = 0; i < iframes.length; i++) {
iframes.item(i).addEventListener("load", function() {
var node = document.createElement('style');
node.appendChild(document.createTextNode('body { background: red; }'));
window.frames[i].document.head.appendChild(node)
})
}
</script>
</body>
</html>
但是 javascript 代码中的循环不起作用。我已经设置了一个 fiddle,其中我将 window.frames[i].document.head.appendChild(node)
更改为 window.frames[i-2].document.head.appendChild(node)
这显示了一种效果,但仅更改了一个 iframe 中的样式,而不是所有 iframe 中的样式:
https://jsfiddle.net/5a8bdynm/
我必须更改什么才能影响所有 iframe?
您正在使用 var
在 for
循环中定义索引 i。所以,你的索引是一个全局变量。
但是您的事件(加载)是异步的 (1),因此当第一个 iframe 加载时,索引的值已经是 3。在这种情况下,window.frames[i]
将始终引用 window.frames[3]
甚至不存在。
如果将 var
替换为 let
,每个循环周期将收到其自己单独的索引值,并且 window.frames[i]
将引用正确的 iframe。
const iframes = document.getElementsByTagName("iframe")
for (let i = 0; i < iframes.length; i++) { // your code}
一般来说,您应该避免使用 var
。
首选 let
和 const
作为最佳实践。
(1) 编辑: 顺便说一句,加载事件的异步性质在这种情况下并不相关,因为代码是事件处理程序的一部分;所以,无论事件是什么,它都会在循环结束后执行(然后,在全局索引变量的值为 3 后)