💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 表单处理 [TOC] ## 表单介绍 在HTML中,表单是由<form>元素来表示的,而在JavaScript中,表单对应的则是HTMLFormElement类型。HTMLFormElement继承了HTMLElement,因此它拥有HTML元素具有的默认属性,并且还独有自己的属性和方法: * `acceptCharset` 服务器能够处理的字符集 * `action` 接受请求的URL * `elements` 表单中所有控件的集合 * `enctype`请求的编码类型 * `length` 表单中控件的数量 * `name` 表单的名称 * `target` 用于发送请求和接受响应的窗口名称 * `reset()` 将所有表单重置 * `submit()` 提交表单 ## 获取表单 `<form>`对象的方法有很多种,如下: * `document.getElementById('myForm');` //使用ID获取<form>元素 * `document.getElementsByTagName('form')[0];`//使用获取第一个元素方式获取 * `document.forms[0]; ` //使用forms的数字下标获取元素 * `document.forms['yourForm'];` //使用forms的名称下标获取元素 * `document.yourForm;` //使用name名称直接获取元素(不推荐) > PS:最后一种方法使用name名称直接获取元素,已经不推荐使用,这是向下兼容的早期用法。问题颇多,比如有两个相同名称的,变成数组;而且这种方式以后有可能会不兼容。 ## 提交表单 通过事件对象,可以阻止submit的默认行为,submit事件的默认行为就是携带数据(默认以get方式)跳转到指定页面(默认为本页)。 ``` addEvent(fm, 'submit', function (evt) { //注意是在form对象上触发submit事件 preDef(evt); }); ``` > PS:submit事件,用传统的方式:fm.onsubmit = function () {}。 > PS:必须把submit事件绑定到form对象上,才可以触发submit事件,只不过触发submit事件的流程是点击input中的submit按钮而已。 > PS:在表单中尽量避免使用name="submit"或id="submit"等命名,这会和submit()方法发生冲突导致无法提交。 ## 表单阻塞问题 提交数据最大的问题就是重复提交表单。因为各种原因,当一条数据提交到服务器的时候会出现延迟等长时间没反映,导致用户不停的点击提交,从而使得重复提交了很多相同的请求,或造成错误、或写入数据库多条相同信息。 有两种方法可以解决这种问题: * 第一种就是提交之后,立刻禁用点击按钮; ```javascript document.getElementById('sub').disabled = true; ``` * 第二种就是提交之后取消后续的表单提交操作。 ```javascript var fm = document.getElementById('myForm'); var flag = false; //设置一个监听变量 addEvent(fm, 'submit', function(evt) { preDef(evt); if (flag == true) return; //如果存在返回退出事件 flag = true; //否则确定是第一次,设置为true,表示我提交过一次了 alert('提交'); setTimeout(function() { fm.submit(); }, 3000); }) ``` ## 重置表单 用户点击重置按钮时,表单会被初始化。虽然这个按钮还得以保留,但目前的Web已经很少去使用了。因为用户已经填写好各种数据,不小心点了重置就会全部清空,用户体验极差。 有两种方法调用reset事件: * 第一个就是直接`type="reset"`即可; * 第二个就是使用`fm.reset()`方法调用即可。 ## 表单字段 如果想访问表单元素,可以使用之前章节讲到的DOM方法访问。但使用原生的DOM访问虽然比较通用,但不是很便利。表单处理中,我们建议使用HTML DOM,它有自己的elements属性,该属性是表单中所有元素的集合。 > PS:表单控件是什么? form里面的input,submit,textarea,select 这些叫做表单控件,其实就是表单元素标签,通过表单元素集合获取第一个元素,非表单控件会被忽略掉。 * `fm.elements[0];` //获取第一个表单字段元素 * `fm.elements['user'];` //获取name是user的表单字段元素 * `fm.elements.length;` //获取所有表单字段的数量 如果多个表单字段都使用同一个name,那么就会返回该name的NodeList表单列表。 fm.elements['sex']; //获取相同name表单字段列表 ##使用ajax提交表单 此处使用到`jquery` or `zepto` $ 使用`serialize()`,`serializeArray()`方法取得表单数据+字符串和对象类型 原始form表单值获取方式(手动): ```javascript $.ajax({ type: "POST", url: "api.php", data: "Name=xiaoming&age=12", success: function(msg){alert(msg);}, error: function(error){alert(error);} }); ``` serialize()方法取值: ```javascript $.ajax({ type: "POST", url:"ajax.php", data:$('#formID').serialize(),// 也可以使用serializeArray,要提交的表单 success: function(msg) {alert(msg);}, error: function(error){alert(error);} }); ``` > 如果明确了是POST方法可以使用 `$.post(url,[data],[success])`方法,如果是GET可使用`$.get(url,[data],[succes])` 关于jquery的ajax请求详细介绍可以参考了(http://hemin.cn/jq/jQuery.ajax.html) ## 我们的开发规范 1. 明确需求 项目开始前,如果项目需要后端参与,需要明确项目需求.如表单的可选字段,必填字段,表单提交次数等详细需求 2. 前端数据验证 如果表单中有些字段明显不合法,前端需要检查过滤,并提示用户重新输入,如果直接提交会造成响应较慢,用户体验就比较差,而且影响服务器处理效率(数据在后端也会进行二次校检,保证数据合法性和安全性) 3. 与后端约定接口和返回数据类型 前端与后端约定字段类型,如姓名(`username`),年龄(`age`) 前后端工作需要明确,后端负责数据的处理与存储,并返回处理结果给前端,前端需要根据返回结果反馈给用户 举例:提交一个姓名和年龄的流程 ```html <script> var api = 'http://wx.diggid.cn/api/ajax/success';//前后端约定数据的提交接口,等后端完成工作后只需要提供给前端此接口即可 </script> <!-- 表单的基本属性--> <form name="userinfo" id="myform" method="POST"> <div id="error"></div> <input name="username" type="text" placeholder="请输入您的姓名" /> <input name="age" type="number" placeholder="请输入年龄" /> <button type="button" id="send-form">提交数据</button> </form> ``` //js处理部分 ```javascript var form = $('#myform'); $('#send-form').click(function(){ //数据验证 var username = form.find('[name="username"]').val(); if(username.length < 2) return alert('请输入您的名字,两个汉字以上'); if(username.length > 12) return alert('您的名字太长了,请保持在12字符以内'); var age = form.find('[name="age"]').val(); if(age < 0 || age > 100) return alert('请输入合法的年龄,0-100岁'); //验证通过,提交数据, //提交数据之前禁用按钮 var that = this; $(that).prop('disabled',true); //提交数据 $.post(api, form.serialize() ,function(res){ //服务器返回结果处理,按钮取消禁用状态 $(that).prop('disabled',false); //根据返回的错误code判断是否处理成功,如果code==0,错误代码等于0表示没有错误 if(res.code == 0){ alert('表单提交成功'); $('#error').html( '' ).hide(); }else{ //表单提交失败,提示用户失败原因 $('#error').html( res.msg ).show(); } }) }); ``` ## 附件 ### 服务器提供的测试接口 可以使用接口,在后端未完成工作之前调试应用是否存在问题 1. http://wx.diggid.cn/api/ajax/success 此接口返回成功状态码 `code=0` ```javascript { "data": [], "code": 0, "msg": "你的操作成功接口" } ``` 2. http://wx.diggid.cn/api/ajax/error 此接口返回失败状态码 `code=-1` ```javascript { "data": [], "code": -1, "msg": "你的操作出现问题" } ``` 3. http://wx.diggid.cn/api/ajax/data 此接口将你提交的数据放在data中原样返回 ```javascript { "data": [], "code": 0, "msg": "返回数据" } ```