【问题标题】:AJAX infinite preventDefault() on AJAX-responded form (vanilla JS)AJAX 响应表单上的 AJAX 无限 preventDefault() (vanilla JS)
【发布时间】:2020-06-30 07:09:20
【问题描述】:

在此过程中,我回顾了几个很棒的问题,以至于我在一天内获得了 40 票的徽章。但是,几乎所有的问题都使用像 jQuery 这样的非 Vanilla 依赖项,或者没有解决我的特定需求。这里有两个很好的例子,但与我的悲伤无关,问题:

我很惊讶这个问题没有被问到,因为我认为自己没有那么有想象力。如果这个问题已经存在,我想请打开一个关于如何更新该问题以便搜索可以找到它的元讨论。

情况:

这是 Vanilla JS,没有依赖项。

脚本使用preventDefault() 来中断form-submitid 标识的按钮,并改为调用AJAX。 AJAX 可以正常工作并正确更改内容。然后,问题就开始了……

此 AJAX 以替换的 div 响应,其中包含 preventDefault() 中断的相同 form。但是,AJAX 无法识别更新后的 form-submit 按钮,在 AJAX 响应 JS 之后,将包含 formdiv 更改为相同的 id

工作流程:

  1. HTML -> <form id="same">(成功)
  2. <form id="same"> -> AJAX(成功,第一次 AJAX 调用)
  3. AJAX -> <form id="same">(成功,第一个 AJAX 响应)
  4. <form id="same"> -> AJAX(中断,第二次 AJAX 调用)

它只在第一次工作;我需要它无限工作。

注意,我需要处理这个特定的form。其他元素,包括可能的其他形式,可能包含在此 AJAX 更改的 div 中。

代码:

index.php

(AJAX改编自MDN - Sending forms through JavaScript: Using FormData bound to a form element

  <script>
  window.addEventListener( "load", function () {
    function sendData() {
      const AJAX = new XMLHttpRequest(); // AJAX handler
      const FD = new FormData( form ); // Bind to-send data to form element

      AJAX.addEventListener( "load", function(event) {
        document.getElementById("ajax_changes").innerHTML = event.target.responseText;
      } ); // Change HTML on successful response
      AJAX.addEventListener( "error", function( event ) {
        document.getElementById("ajax_changes").innerHTML =  'Oops! Something went wrong.';
      } );
      AJAX.open( "POST", "ajax_responder.php" ); // Send data, ajax_responder.php can be any file or URL
      AJAX.send( FD ); // Data sent is from the form

    } // sendData() function

    const form = document.getElementById( "ajaxForm" ); // Access <form id="ajaxForm">, id="ajaxForm" can be anything
    form.addEventListener( "submit", function ( event ) { // Takeover <input type="submit">
      event.preventDefault();
      sendData();
    } );

  } );
  </script>

  <div id="ajax_changes">Replace me with AJAX<br>
    <form id="ajaxForm">
      <input type="text" value="AJAX" name="foo">
      <input type="text" value="5" name="bar">
      <input type="submit" value="Form AJAX!">
    </form>
  <!-- Possible other HTML elements and/or forms I do not want to process with that same AJAX -->
  </div>

ajax_responder.php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $foo = $_POST['foo'];
  $bar = $_POST['bar'];

echo '
'.$foo.'
<br>
'.$bar.'
<br>
<form id="ajaxForm">
  <input type="text" value="'.$foo.'" name="foo">
  <input type="text" value="'.$bar.'" name="bar">
  <input type="submit" value="Form AJAX!">
</form>
<!-- Possible other HTML elements and/or forms -->
';
}

问题

让 AJAX 继续作用于同一响应包含的 form-submit 元素的“正确”方式是什么?

我考虑过不以相同form 回复的方式:

  • 让 AJAX 只响应和更改特定的小元素
  • form 重新定位到 AJAX 更改的内容之外

但这两个似乎都很复杂。

必须有某种方式告诉 AJAX 在 form-submit 按钮上的 preventDefault() 该按钮已被 AJAX 更新。我只是不知道那是什么。

或者,还有其他仍然涉及 Vanilla JS 的解决方案吗?

【问题讨论】:

  • 您将事件监听器绑定到ajaxForm 表单。然后你替换它(=删除并添加新的),事件监听器也消失了。尝试仅替换表单内容或将事件监听器绑定到容器 div。
  • 您可以签入开发工具。用ajax调用替换后看看是否有附加到表单的事件。
  • 当您将其附加到 div 时,它会中断,因为您提交的是 div,而不是表单。事件冒泡,所以它确实到达了 te div,你只需要应用一些逻辑来提交表单而不是容器 div。
  • “将它绑定到容器 div 会中断 [...]” - 那么您究竟做了什么更改?如果你现在只是把const form = document.getElementById( "ajaxForm" )变成了const form = document.getElementById( "ajax_changes" ),那么你当然需要相应地修改这部分,const FD = new FormData( form );
  • 您的问题的答案是:不,没有。一旦你从 DOM 中移除了表单,eventListener 就会被移除。

标签: javascript php ajax forms preventdefault


【解决方案1】:

您正在将 eventListener 绑定到 &lt;form&gt; ajaxForm。然后替换它(= 从 DOM 中删除 &lt;form&gt; 并将新的 &lt;form&gt; 添加到 DOM)。在这种情况下,eventListener 也会被移除。

要在新表单上添加 eventListener,您可以:

• 仅替换&lt;form&gt; 的内容。在这种情况下,不会删除 DOM 元素,因此 eventListener 保持不变 (不要忘记删除 php 响应中的 &lt;form&gt; 标签)。恕我直言,这是最简单的方法。

document.getElementById("ajaxForm").innerHTML=
                             event.target.responseText;

• 每次&lt;form&gt; 更改时绑定一个新的事件监听器:

AJAX.addEventListener( "load", function(event) {
        document.getElementById("ajax_changes").innerHTML =
                             event.target.responseText;
//=====> bind new eventListener here <======
      } );

您可以创建一个在加载时也可以在 ajax 响应中调用的函数

function addListenerToForm(){
    document.getElementById( "ajaxForm" ).addEventListener( "submit", function ( event ) {
       event.preventDefault();
       sendData();
    });
  }

• 将 eventListener 绑定一次到容器&lt;div&gt;

document.getElementById( "ajax_changes" ).addEventListener( "submit", function ( event ) {
  event.preventDefault();
  sendData();
});

function sendData(){
   const AJAX = new XMLHttpRequest(); // AJAX handler
   const form = document.getElementById( "ajaxForm");               
   const FD = new FormData( form );
   ...
   }

【讨论】:

    【解决方案2】:

    鉴于above answer 的解决方案“每次&lt;form&gt; 更改时都绑定一个新的事件监听器”

    我换了const

    const form = document.getElementById( "ajaxForm" );
    

    var

    var form = document.getElementById( "ajaxForm" );
    

    然后把它和它的监听器放在这一行

    //=====> bind new eventListener here <======
    

    没有任何声明

    form = document.getElementById( "ajaxForm" );
      form.addEventListener( "submit", function ( event ) {...
    

    它奏效了!非常感谢!我是一个快乐的编码土豆。

    我的新 JavaScript 是:

      <script>
      window.addEventListener( "load", function () {
        function sendData() {
          const AJAX = new XMLHttpRequest(); // AJAX handler
          const FD = new FormData( form ); // Bind to-send data to form element
    
          AJAX.addEventListener( "load", function(event) {
            document.getElementById("ajax_changes").innerHTML = event.target.responseText;
          } ); // Change HTML on successful response
    
          AJAX.addEventListener( "error", function( event ) {
            document.getElementById("ajax_changes").innerHTML =  'Oops! Something went wrong.';
          } );
    
          AJAX.open( "POST", "ajax_responder.php" ); // Send data, ajax_responder.php can be any file or URL
    
          AJAX.send( FD ); // Data sent is from the form
    
          AJAX.addEventListener( "load", function(event) {
            document.getElementById("ajax_changes").innerHTML =
              event.target.responseText;
              // Bind a new eventListener everytime the <form> is changed:
              form = document.getElementById( "ajaxForm" ); // Access <form id="ajaxForm">, id="ajaxForm" can be anything
              form.addEventListener( "submit", function ( event ) { // Takeover <input type="submit">
                event.preventDefault();
                sendData();
              } ); // End new event listener
          } );
        } // sendData() function
    
        var form = document.getElementById( "ajaxForm" ); // Access <form id="ajaxForm">, id="ajaxForm" can be anything
        form.addEventListener( "submit", function ( event ) { // Takeover <input type="submit">
          event.preventDefault();
          sendData();
        } );
    
      } );
      </script>
    

    【讨论】:

      猜你喜欢
      • 2013-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多