有没有办法为 AJAX 表单执行类似于 onbeforeunload 的操作?

Is there a way to do something similar to onbeforeunload for an AJAX form?

可悲的是,我们不得不使用自制的类似 SPA 的引擎,它劫持了所有导航并通过 ajax 实现。

我正在寻找一种能够将标签添加到 form 的方法,可能是这样的:

<form data-confirm-unsaved=""></form>

这应该会导致卸载此 form 的绑定,无论是实际的整个页面卸载(例如有人关闭了选项卡或输入 URL)还是点击任何被劫持的导航元素...但我不希望它在 form 是 submitted/saved 时被触发。

我有一个不工作代码的开始大纲:

$('[data-confirm-unsaved]').on('beforeunload', function (e) {
        let isUnload = true;
        let message = $(this).attr('[data-confirm-unsaved]');
        if (message == '')
            message = "This data is unsaved. Are you certain that you want to cancel?";

        if (isFormDirty($(this)))
            isUnload = confirm(message);

        if (isUnload)
            e.preventDefault();
    });

当然我不能将 beforeunload 事件绑定到 form... 只有 window,我能得到一些关于我将如何去做的线索吗?

预期的结果是,当 form 通过除提交以外的任何方式卸载时,如果他们真的想要这样做,就会出现确认的脏输入。

您可以使用附加到 <body>MutationObserver,并将 childList 选项设置为 true,在 MutationEvent,检查 <form> 是否删除节点。

<body>
  <form id="form">
    <input>
  </form>
  <script>
    const form = document.getElementById("form");
    
    const observer = new MutationObserver(([{removedNodes}]) => {
      
      if (removedNodes.length) {
        // do stuff if `form` is removed from `document.body`
        checkRemovedNodes: for (const node of removedNodes) {
          if (node === form) {
            console.log(`${node.tagName}#${node.id} removed from document`);
            break checkRemovedNodes;
          }
        }
      }

    });
    // remove `form` from `document` in `3000` milliseconds
    observer.observe(document.body, {
      childList: true
    });

    setTimeout(() => document.body.removeChild(form), 3000);
  </script>
</body>