我使用空框架来处理伪异步表单提交。对于那些不熟悉该技术的人来说,其想法是在表单的
name
属性中引用框架的 target
属性,以便表单的 action
的 URI 在框架中解析,并且用户体验不会受到影响。没被打断。
为了向用户反馈,我需要使用脚本来侦听表单上的
load
或 error
事件,并且因为这有效地使整个 UX 脚本依赖,所以我只注入框架并添加表单的通过脚本进行目标引用。
问题是框架一旦注入页面就会触发加载事件:默认行为。
我可以使用 jQuery 的
one
方法和 e.stopImmediatePropagation()
(这里)来缓解这个问题,或者我可以注入框架并then绑定事件(这里)。但这两个选项确实违反直觉——代码当然需要注释以避免看起来像一个错误。
TL;DR:有什么方法可以修改或限定 iframe 来阻止它在注入时触发错误的加载事件?
我尝试过的事情
src
属性src
设置为 about:blank
(上面是隐含的)src
设置为 #
src
设置为 javascript:void 0
src
设置为空数据-URI data:text/plain;base64,;
srcdoc
设置为空或接近空的字符串这是不可能的,正如您所说,默认
src
设置为 about:blank
,任何其他值都会触发 load
事件或 error
一个。
因此,最干净的解决方案可能是仅在触发表单的提交事件时才开始侦听这些事件:
const frame = document.createElement("iframe");
frame.name = "frame";
document.body.append(frame);
const form = document.querySelector("form");
form.addEventListener("submit", (evt) => {
const controller = new AbortController();
const { signal } = controller;
const handler = (evt) => {
console.log("Request", evt.type === "error" ? "failure" : "success");
controller.abort(); // kill us and the other listener
};
frame.addEventListener("load", handler, { signal });
frame.addEventListener("error", handler, { signal });
});
<form
target=frame
method=post
action="https://stacksnippets.net/js">
<button>post it</button>
<textarea name=html>Some content</textarea>
</form>
但是应该注意的是,要触发 error 事件,您需要有一个浏览器无法在 iframe 中打开的响应,而浏览器可以在 iframe 中打开很多内容,而且,大多数服务器在遇到错误时确实会发送正确的 HTML 页面。因此,在大多数情况下,这不会让您知道请求失败,即使 404 错误也会触发 iframe 的 load 事件。
因此,如果您处于同源情况,最好的方法可能是使用 AJAX 来发出请求。从那里您可以检查响应的状态代码,甚至可以让服务器为您提供有用的信息,例如作为 JSON 响应。 然后,您可以使用作为文本使用的响应来填充 iframe 的
srcdoc
。 (外部小提琴,因为 StackSnippet 的空源帧无法发出同源请求)。
var e = $('<iframe>');
e.appendTo('body');
e.on('load', function(){
alert('Loaded!')
});
在 JavaScript 中,“空白”IFRAME 的 URL 与包含窗口的 URL 相同。 因此必须验证以下条件:
function do_Onload(node) {
if (node.src == window.location.href) {
//this is the load event for the blank iframe
}
}
在 IFRAME 上:
<iframe onload="do_Onload(this)"></iframe>