如何停止在注入时触发加载事件的空 iframe?

Bar*_*ney 5 html javascript dom javascript-events

我正在使用一个空框架来处理伪异步表单提交。对于那些不熟悉该技术的人,其想法是name在表单的target属性中引用框架的属性,这样表单的URI 就会action在框架中解析,并且不会中断用户体验。

为了向用户反馈,我需要使用脚本来侦听表单上的loaderror事件,并且因为这有效地使整个 UX 脚本依赖,所以我只注入框架并通过脚本添加表单的目标引用。

问题是框​​架会在注入页面后立即触发加载事件:默认行为

我可以使用 jQuery 的one方法和e.stopImmediatePropagation()这里)来缓解这个问题,或者我可以注入框架然后绑定事件(这里)。但是这两个选项都非常违反直觉——代码当然需要注释以避免看起来像一个错误。

TL;DR:有什么办法可以修改或限定 iframe 以阻止它首先在注入时触发错误的加载事件?

我试过的

  1. src属性
  2. src设置为about:blank(上面隐含的)
  3. src 设置 #
  4. src 设置 javascript:void 0
  5. src 设置为空数据URI data:text/plain;base64,;
  6. srcdoc 设置为空或接近空的字符串

Kai*_*ido 0

正如您所说,这是不可能的,默认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 });
});
Run Code Online (Sandbox Code Playgroud)
<form
  target=frame
  method=post
  action="https://stacksnippets.net/js">
<button>post it</button>
<textarea name=html>Some content</textarea>
</form>
Run Code Online (Sandbox Code Playgroud)

但应该注意的是,要触发错误事件,您需要有一个浏览器无法在 iframe 中打开的响应,并且浏览器可以在 iframe 中打开很多内容,而且,大多数服务器都这样做当遇到错误时发送正确的 HTML 页面。因此,在大多数情况下,这不会让您知道请求失败,即使 404 错误也会触发 iframe 的加载事件。

因此,如果您处于同源情况,最好的方法可能是使用 AJAX 来发出请求。从那里您可以检查响应的状态代码,甚至可以让服务器为您提供有用的信息,例如作为 JSON 响应。然后,您可以srcdoc使用作为文本使用的响应来填充 iframe 的 。(外部小提琴,因为 StackSnippet 的空源帧无法发出同源请求)。