背景
昨天表弟问了我一个问题
我立马会回了一段代码过去。岂能说不会!
分析
其实要快速获取表单数据的功能并不复杂。就两步
分析需求编写代码
- 要清楚常见的表单有哪些
- 根据表单获取到的数据结构是什么样子
常见的表单标签
email、date等存在兼容性的表单标签可以忽略。
文本框 input[type=text]
<input type="text">
密码框 input[type=password]
<input type="password">
文本域 textarea
<textarea></textarea>
下拉列表 select
<select></select>
单选框 input[type=radio]
<input type="radio">
复选框 input[type=checkbox]
<input type="checkbox">
文件选择框 input[type=file]
<input type="file">
获取表单值的方式
不同的标签,有不同的获取它们值的方式
文本框和密码框和文本域
他们都是通过 value属性直接获取值
dom.value
下拉列表
下拉列表其实也可以多选的 multiple
<select name="city" multiple> <option value="广州">广州</option> <option value="东莞">东莞</option> <option value="佛山">佛山</option> </select>
- 当下拉列表 没有添加多选时,直接 通过value属性即可获取到对应值。
dom.value
- 当下拉列表 添加多选时 ,获取获取子元素
option
,通过判断是否selected
来获取选中的值。
const select = document.querySelector("select") for (let index = 0; index < select.children.length; index++) { const option = select.children[index]; if (option.select) { console.log(option.value); } }
单选框
单选框的特点是 同一组单选框都会有同一个name属性。并且选中的单选框的checked属性为true
<input type="radio" name="gender" value="男" checked> 男 <input type="radio" name="gender" value="女"> 女
因此便可以通过这个特点来获取选中的单选框。获取的方式有两种
document.querySelector("[name=gender]:checked").value
或者
const radios = document.querySelectorAll("[name=gender]") for (let index = 0; index < radios.children.length; index++) { const radio = radios.children[index]; if (radio.checked) { console.log(radio.value); break } }
复选框
复选框的用法和单选框类似,只不过复选框是可以拥有多个值
<input type="checkbox" name="hobby" value="唱"> 唱 <input type="checkbox" name="hobby" value="跳"> 跳 <input type="checkbox" name="hobby" value="rap"> rap <input type="checkbox" name="hobby" value="打篮球"> 打篮球
它的获取方式也有两种,一种直接querySelectorAll
带上合适的选择器即可
document.querySelectorAll("[name=hobby]:checked").value
另外一种也是遍历
const checkboxs = document.querySelectorAll("[name=hobby]") for (let index = 0; index < checkboxs.children.length; index++) { const checkbox = checkboxs.children[index]; if (checkbox.checked) { console.log(checkbox.value); } }
文件选择框
最后是文件选择框,文件选择框需要通过 dom.files来获取即可,当然,它也可以通过添加 multiple
属性来实现多选
<input type="file" name="avatar" multiple>
dom.files // 获取到选中的文件
期望得到的数据结构
当我们了解了常见的表单标签后,那么我们要假设期待得到的数据结构
提炼关键信息:
- 当表单是 文本框、密码框、文本域 、单选框时,我们都可以直接通过
value属性
来获取数据,并且存放时,他们是字符串类型
{ 文本框:"用户名", 密码框:"密码", 性别:"男" }
- 当表单是下拉列表时,存放它的值需要分情况
- 单选的下拉列表 (没有
multiple
属性),是字符串类型
{
城市:"广州"
}
- 多选的下拉列表 (有
multiple
属性),是数组类型
{
城市:["广州","东莞"]
}
{
喜好:["唱","跳","rap"]
}
- 当表单是 文件选择框时,存放它的数据,是数组(因为可能多选文件)
{
照片:[照片1,照片2]
}
编码流程
完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>快速获取表单数据</title> </head> <body> <form> <!-- 输入姓名的文本框 --> <div> <input type="text" placeholder="请输入姓名" name="userName" /> </div> <!-- 选择性别的单选按钮 --> <div> <input type="radio" name="gender" value="男" /> 男 <input type="radio" name="gender" value="女" /> 女 </div> <!-- 选择是否在世的单选按钮 --> <div> <input type="radio" name="alive" value="还在" checked /> 还在 <input type="radio" name="alive" value="上天了" /> 上天了 </div> <!-- 选择兴趣爱好的复选框 --> <div> <input type="checkbox" name="hobby" value="唱" /> 唱 <input type="checkbox" name="hobby" value="跳" /> 跳 <input type="checkbox" name="hobby" value="rap" /> rap <input type="checkbox" name="hobby" value="打篮球" /> 打篮球 </div> <!-- 选择城市的下拉框 --> <div> <select name="city" multiple> <option value="广州">广州</option> <option value="东莞">东莞</option> <option value="佛山">佛山</option> </select> </div> <!-- 输入个人简介的文本域 --> <div> <textarea name="intro"></textarea> </div> <!-- 上传头像的文件输入框 --> <div> 上传头像 <input type="file" name="avatar" multiple /> </div> <!-- 提交按钮 --> <div> <button>提交</button> </div> </form> <script> // 获取表单元素并存储在常量form中 const form = document.querySelector('form') // 为表单添加提交事件监听器 form.addEventListener('submit', function (e) { // 阻止默认的表单提交行为 e.preventDefault() // 序列化表单数据,并存储在常量data中 const data = serialize(form) console.log(data) }) // 定义序列化函数,接收一个表单元素作为参数 function serialize(tempForm) { // 创建一个空对象,用于存储序列化后的表单数据 const data = {} // 获取表单中所有具有"name"属性的字段 const formFieldList = tempForm.querySelectorAll('[name]') // 遍历所有表单字段 formFieldList.forEach((field) => { // 检查字段的类型和标签名 if ( field.type === 'text' || field.type === 'password' || field.tagName === 'TEXTAREA' ) { // 如果是文本输入框或文本域,则将其值存储在data对象中 data[field.name] = field.value } else if (field.tagName === 'SELECT') { // 如果是下拉框 if (field.multiple) { // 如果是多选下拉框,使用reduce将选中的项的值存储在数组中 data[field.name] = [...field.children].reduce((a, b) => { if (b.selected) { a.push(b.value) } return a }, []) } else { // 如果是单选下拉框,直接将选中的项的值存储在data对象中 data[field.name] = field.value } } else if (field.type === 'radio' && field.checked) { // 如果是单选按钮且被选中,则将其值存储在data对象中 data[field.name] = field.value } else if (field.type === 'checkbox' && field.checked) { // 如果是复选框且被选中 if (!data[field.name]) { // 如果该字段在data对象中不存在,创建一个数组存储值 data[field.name] = [field.value] } else { // 如果已存在,将值添加到数组中 data[field.name].push(field.value) } } else if (field.type === 'file') { // 如果是文件上传字段 // 如果支持多文件上传,将文件对象数组存储在data对象中 data[field.name] = field.files } }) // 返回包含序列化后数据的对象 return data } </script> </body> </html>