如何阻止空iframe在注入时触发加载事件

How to stop an empty iframe triggering a load event on injection?

本文关键字:加载 事件 注入 何阻止 iframe      更新时间:2023-09-26

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

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

问题是,框架将触发加载事件一旦注入到页面:默认行为。

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

TL;DR:是否有任何方法可以修改或限定iframe以阻止它在注入时触发错误的加载事件?

What I've try

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

这是不可能的,正如您所说,默认的src被设置为about:blank,任何其他值将触发load事件或error事件。

因此,最简洁的解决方案可能是仅在触发表单的submit事件时才开始侦听这些事件:

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的空起源帧不能使同源请求)。

首先将iframe放入文档中,然后注册侦听器:

var e = $('<iframe>');
e.appendTo('body');
e.on('load', function(){
  alert('Loaded!')
});