Javascript 无法将脚本加载到iframe中
测试页面: 在这个测试页面上,你可以看到3个相互嵌入的Javascript 无法将脚本加载到iframe中,javascript,html,iframe,Javascript,Html,Iframe,测试页面: 在这个测试页面上,你可以看到3个相互嵌入的。每个在其标记中包含一个标记 问题是:浏览器将仅加载第一个中的。另外两个标记将出现在dom中,但浏览器甚至不会尝试加载它们。这个问题不是特定于浏览器的,它可以在chrome、firefox、ie中重新生成。这个问题不能通过添加超时或在附加脚本之前等待来解决。所有iFrame都以编程方式生成内容似乎很重要;如果用带有实际src链接的iframe替换此iframe,则问题将消失 问题是:如何将脚本加载到iFrame 2和iFrame 3中 完整测
。每个
在其
标记中包含一个
标记
问题是:浏览器将仅加载第一个
中的
。另外两个
标记将出现在dom中,但浏览器甚至不会尝试加载它们。这个问题不是特定于浏览器的,它可以在chrome、firefox、ie中重新生成。这个问题不能通过添加超时或在附加脚本之前等待来解决。所有iFrame都以编程方式生成内容似乎很重要;如果用带有实际src链接的iframe替换此iframe,则问题将消失
问题是:如何将脚本加载到iFrame 2和iFrame 3中
完整测试代码:
// It doesn't matter if the scripts exist or not
// Browser won't try to load them either way
var scripts = [
'//testdomain.test/script1.js',
'//testdomain.test/script2.js',
'//testdomain.test/script3.js'
];
function createIFrame(win, onCreated) {
var iframe = win.document.createElement('iframe');
iframe.onload = function () {
onCreated(iframe);
};
win.document.body.appendChild(iframe);
}
function loadScript(win, url) {
var script = win.document.createElement('script');
script.src = url;
script.onload = function() {
console.log("Script " + url + " is loaded.");
};
win.document.getElementsByTagName('head')[0].appendChild(script);
}
createIFrame(window, function(iframe1) {
loadScript(iframe1.contentWindow, scripts[0]);
createIFrame(iframe1.contentWindow, function (iframe2) {
loadScript(iframe2.contentWindow, scripts[1]);
createIFrame(iframe2.contentWindow, function (iframe3) {
loadScript(iframe3.contentWindow, scripts[2]);
});
});
});
您的代码运行正常--> 确保在或上执行createIFrame
在这个问题中,你可以看到我在宣布协议:
/* This is valid to omit the http:/https: protocol.
In that case, browser should automatically append
protocol used by the parent page */
var scripts = [
'//testdomain.test/script1.js',
'//testdomain.test/script2.js',
'//testdomain.test/script3.js'
];
问题是,通过编程创建的iFrame具有协议about:
(或javascript:
,具体取决于创建它们的方式)。我仍然无法解释为什么第一个脚本正在加载,或者为什么其他两个脚本根本没有显示在“网络”选项卡中,但我想这并不重要
解决方案:要么显式使用https://
,要么使用类似以下代码的程序附加协议:
function appendSchema(win, url) {
if (url.startsWith('//')) {
var protocol = 'https:';
try {
var wPrev = undefined;
var wCur = win;
while (wPrev != wCur) {
console.log(wCur.location.protocol);
if (wCur.location.protocol.startsWith("http")) {
protocol = wCur.location.protocol;
break;
}
wPrev = wCur;
wCur = wCur.parent;
}
} catch (e) {
/* We cannot get protocol of a cross-site iframe.
* So in case we are inside cross-site iframe, and
* there are no http/https iframes before it,
* we will just use https: */
}
return protocol + url;
}
return url;
}
我成功地使用了一种比OP在报告中提出的更简单的方法。我使用以下方法生成URL:
new URL(scriptURL, window.location.href).toString();
其中,scriptURL
是需要固定以获得适当协议的URL,window
是保存脚本的iframe
元素的父元素。这可以处理与OPs示例URL不同的场景:如相对URL(./foo.js
)或不以主机开头的绝对URL(/foo.js
)。以上代码在我的情况下就足够了
如果我要通过OP使用的窗口层次结构复制搜索,我可能会执行以下操作。这是打字脚本代码。去掉类型注释以获得普通JavaScript
function url(win: Window, path: string): string {
// We search up the window hierarchy for the first window which uses
// a protocol that starts with "http".
while (true) {
if (win.location.protocol.startsWith("http")) {
// Interpret the path relative to that window's href. So the path
// will acquire the protocol used by the window. And the less we
// specify in `path`, the more it gets from the window. For
// instance, if path is "/foo.js", then the host name will also be
// acquired from the window's location.
return new URL(path, win.location.href).toString();
}
// We searched all the way to the top and found nothing useful.
if (win === win.parent) {
break;
}
win = win.parent;
}
// I've got a big problem on my hands if there's nothing that works.
throw new Error("cannot normalize the URL");
}
如果窗口链没有产生任何有用的结果,我没有默认的返回值,因为这将表明一个比生成URL更大的问题。我的设置中的其他地方可能有问题。您的控制台中有哪些错误?谢谢。尽管你的回答没有解决我的问题,但它提供了解决问题的重要线索(见我的答案)。
function url(win: Window, path: string): string {
// We search up the window hierarchy for the first window which uses
// a protocol that starts with "http".
while (true) {
if (win.location.protocol.startsWith("http")) {
// Interpret the path relative to that window's href. So the path
// will acquire the protocol used by the window. And the less we
// specify in `path`, the more it gets from the window. For
// instance, if path is "/foo.js", then the host name will also be
// acquired from the window's location.
return new URL(path, win.location.href).toString();
}
// We searched all the way to the top and found nothing useful.
if (win === win.parent) {
break;
}
win = win.parent;
}
// I've got a big problem on my hands if there's nothing that works.
throw new Error("cannot normalize the URL");
}