如何在表单提交时发送ajax请求而不影响实际表单

Posted

技术标签:

【中文标题】如何在表单提交时发送ajax请求而不影响实际表单【英文标题】:How to send an ajax request on form submit without affecting the actual form 【发布时间】:2020-11-08 09:52:21 【问题描述】:

我想创建一个注册表单来验证您的输入,然后向 php 页面发送 AJAX 请求以检查您的用户名是否已被使用。之后它将提交实际的表单(位置在一个动作属性中)。

function validate() 
  if (fullname.length < 90)  /*this is validating the form*/
    var username_input = document.forms["myform"]["username"].value;
    if (window.XMLHttpRequest) 
      var usernamecheck = new XMLHttpRequest();
     else if (window.ActiveXObject) 
      var usernamecheck = new ActiveXObject("Microsoft.XMLHTTP");
    
    usernamecheck.open("POST", "reciever.php", true);
    usernamecheck.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    usernamecheck.send("user=" + username_input); /*sending username to check if it exists*/
    usernamecheck.onreadystatechange = function() 
      if (usernamecheck.readyState == 4 && this.status == 200) 
        if (usernamecheck.responseText == "user") 
          alert('username has already been used');
          return false;
        
      
    ;

    var contactcheck = new XMLHttpRequest(); /*second request*/
    contactcheck.open("POST", "reciever.php", true);
    contactcheck.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    contactcheck.send("contact=" + contactw);
    contactcheck.onreadystatechange = function() 
      if (contactcheck.readyState == 4 && this.status == 200) 
        if (contactcheck.responseText == "contact") 
          alert('email has already been used');
          return false;
        
      
    ;
  
  /*reference 1 (see below)*/

我的问题是表单在 AJAX 运行之前就提交了,如果我在脚本显示“引用 1”的地方添加 return false;,AJAX 就会运行,但表单没有提交。

【问题讨论】:

能否添加监听提交事件的部分并调用validate 函数。这需要在IE9及以下的旧机器上运行吗? 【参考方案1】:

您的问题与此类似:

check if username exists in real-time through AJAX in php with mysql

引用帖子:

“像这样使用 jQuery 在 javascript 中发送您的数据:”

$.post( "check.php",  user: $("#username").val() , function (data)
  if(data=='1')
   //do 1
  
  elseif(data=='0')
    //do 0
  
);

在你的 check.php 中获取这样的用户名

//some basic validation
if(!isset($_POST['user'] || empty($_POST['user']))


       echo '0'; exit();
    

$username = trim($_POST['user']); 

“为了让它正常工作,你 check.php 必须返回 1 或 0,不要在此处或任何地方回显 mysql 错误。如果发生任何错误,只需回显 0。”

【讨论】:

【参考方案2】:

如果您的函数用作事件处理程序,例如addEventListener('submit', validate)onsubmit="validate()",那么您应该检查Event 对象发送与提交事件并防止表单的默认提交行为。

您可以使用event.preventDefault() 方法来做到这一点,就像它所说的那样,它可以防止表单的默认行为,即提交。

但是您的return false 语句不起作用的原因是XMLHttpRequest.send() 的异步性质。这意味着该函数不会等待 return 语句,因为它位于稍后调用的函数内部。他的行为的原因是让其他代码在您等待服务器响应时运行,而不是在请求完成之前等待代码。

您还可以在一个请求中向服务器发送多个值,而不是执行两个单独的请求。应尽可能优化 AJAX 请求,因为它们(可能)对客户端和服务器都造成负担。

请参阅下面的 sn-ps,了解如何完成上述所有操作。

function validate(event) 
  if (fullname.length >= 90) 
    return; // Stop function if condition is not met.
  
  event.preventDefault(); // Prevent form from submitting.
  var form = event.target; // The target is the form that is submitting.
  var userName = form.elements['username'].value;
  var email = form.elements['email'].value; // I assume this was missing.
  var request;
  if (window.XMLHttpRequest) 
    request = new XMLHttpRequest();
   else if (window.ActiveXObject) 
    request = new ActiveXObject("Microsoft.XMLHTTP");
  
  request.open("POST", "reciever.php", true);
  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  request.onreadystatechange = function() 
    if (this.readyState == 4 && this.status == 200) 
      var response = this.responseText;
      if (response === "user") 
        alert('Username has already been used');
       else if (response === "email") 
        alert('Email has already been used');
      
    
  ;
  request.send('user=' + userName + '&email=' + email); // Send both user name and email values.

您似乎使用了像ActiveXObject 这样的遗留代码,当前浏览器不再使用它。如果您真的需要它用于较旧的浏览器,那么您很好。如果您喜欢更现代的方法并且不需要支持旧浏览器,请查看下面的示例。它(几乎)做同样的事情,但语法不同。

const alerts = 
  'user': 'Username has already been used',
  'email': 'Email has already been used'
;

async function validate(event) 
  if (fullname.length >= 90) return; 
  event.preventDefault();
  const formData = new FormData(event.target);
  try 
    const response = await fetch('reciever.php', 
      method: 'POST',
      body: formData
    
    if (!response.ok) 
      throw new Error(`
        Check has failed. - 
        $response.status: 
        $response.statusText`
      );
    
    const text = await response.text();
    if (text in alerts) alert(alerts[text]);
   catch (error) 
    console.error(error);
  


【讨论】:

以上是关于如何在表单提交时发送ajax请求而不影响实际表单的主要内容,如果未能解决你的问题,请参考以下文章

如何验证表单数据,然后通过 AJAX 发送,然后在同一页面上显示提交的结果

提交常规表单之前的 AJAX 请求

用javascript控制form表单只提交请求,而不跳转

更改提交时 Ajax 表单上的 CSRF 令牌不匹配

如何使用 ajax 提交带有 3 个提交按钮的表单而不重定向到 Laravel 中的表单操作 url?

使用Jquery时无法读取数据库,Ajax提交表单而不刷新页面