
前端开发要知道的网络基础
本文介绍了前端开发中网络基础的关键概念,包括HTTP状态码与REST API的关系、TCP/IP协议的三次握手与四次挥手、DNS和DHCP协议、用户状态校验、常见网络攻击及其防范、HTTPS协议及其加密算法、HTTP/2.0的特性以及WebSocket协议的应用。重点强调了安全性和性能优化的重要性。
本文介绍了HTML表单的基本知识,包括表单的定义、元素、提交方法、验证方式及其在组件库中的应用。表单用于收集用户输入,支持多种元素如<input>、<select>和<textarea>,并通过action和method属性定义提交行为。强调了客户端和服务端的验证方式,以及使用JSON格式提交表单数据的优势。最后,讨论了在Ant Design与Vue中的表单使用方法。
自己也做了一段时间前端了,最近做项目的时候才发现自己对表单(form)元素一无所知,当年写登录框都是两个<input>
直接拼在一起的(笑)。今天就专门来学习一下表单相关的知识。
本篇将从最基础的表单知识(如定义和概念)等入手 (毕竟之前也没系统了解过) ,再理解表单的本质:我们为什么需要表单、如何设计表单、与POST之间的联系等,最后再了解antd中的表单元素<a-form>
的使用与实践。
这是一个最基础的问题,就是表单(form)的定义到底是什么样的?(当然,这里只讨论最基本的HTML表单)
HTML 表单用于搜集不同类型的用户输入。HTML 表单包含表单元素,表单元素指的是不同类型的 input 元素、复选框、单选按钮、提交按钮等等。
——W3CSchool
从上述定义来看,我们可以简单地将表单(form)理解为浏览器内建的一种用户输入集合的数据结构,浏览器内建的好处在于其通用性和性能优化(基于C++而非JS)。
表单标签<form>
支持的元素有:
<input>
:最重要的表单元素有多种多样的类型
<label>
:与input连用,for
属性与input的id
属性配合,示例如下:<form>
<label for=“name”>姓名</label>
<input id="name" name="name" type="text" />
</form>
<select>
:下拉选框,示例如下<form>
<select name="city">
<option value="0">北京</option>
<option value="1">上海</option>
</select>
</form>
<textarea>
:大段文本框(支持多行)我们有了收集信息的表单元素,要如何将信息提交给服务器呢?
submit
按钮为我们在页面上提交了一个显式的提交入口,除此之外,其他默认方法(如Enter提交)也可以触发提交操作<form>
的action
和method
*属性定义提交操作HTML 表单的提交行为有如下规则:
name
*属性的表单元素 (这一点非常重要)action
虽然名字叫“行为”,但是它实际上只接收URL (绝对或相对) ,提交表单时会向这个URL发送HTTP请求(如我的博客中有一个表单,action
值为statistics.asp
,那么最终请求的URL就是chlorinec.top/statistics.asp
)
action
属性被忽略,则默认是当前页面method
属性对应了HTTP请求头中的方法
默认情况下为GET方法,在Query中添加信息 (重要!)
更多情况下,应该使用POST方法,它将表单信息存储在报文负载中而非Query Param中
默认的POST表单报文如下(示例来自MDN)
POST / HTTP/2.0
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
say=Hi&to=Mom
表单相比一个个单列的数据输入元素的优势就在于它提供了一种将数据组织起来的形式,这样一种(浏览器内建支持)聚合的数据结构可以为我们提供很多便利:
那么,为什么我们需要验证表单呢?这就要提到一句著名的原则了:后端永远不要相信前端传回的数据(前端亦然)。换句话说就是,你在任何情况下拿到了源自非自己的数据时都应该校验格式,你的后端同事如此,你的用户更应如此!因为你永远不知道你的顾客会不会在你的酒馆点一份炒饭然后拿起汤姆逊一顿突突把服务器打得稀巴烂。
对于数据校验(data validation),一般有两种方式:
客户端校验:在HTML中这发生在浏览器中,它可以实时地反馈用户的输入结果,通常发生在正式提交之前,有较好的用户体验
校验属性允许你对表单元素定义一些规则,除此之外你还可以设计一些CSS伪类来自定义校验结果的反馈形式。
:valid
和:invalid
*将分别定义校验通过和失败时表单元素的样式required
属性:必填字段pattern
属性:基于正则表达式进行字符串匹配minlength
和maxlength
JS中直接通过DOM或者ref去读取表单元素的值进行校验(设置valid状态)是非常灵活的,这里就不再赘述。
JS和DOM提供了一套用于校验的API来反应校验结果到元素上,可以在绝大多数的表单元素中调用(HTMLXXXElement
),校验成功与否(invalid事件)仍会反映在伪类上!
校验相关方法:
checkValidity()
方法会立刻进行一次校验,返回bool值,可能**触发****invalid
*事件reportValidity()
方法会返回当前校验结果,并反映校验消息给用户setCustomValidity(message)
方法为元素添加一个自定义的错误消息;如果设置了自定义错误消息,该元素被认为是无效的,则显示指定的错误。校验相关属性:(懒得打字了,直接截图MDN了)
其实如果从程序员角度出发,这个问题已经被我们回答了:如果有一个已经造好了的轮子,它能满足我们的现有需求,还具有性能优势和兼容性优势,我们没有任何理由不去使用它而去再造一个自己的轮子 —— 这就是使用表单的最淳朴的理由。
但现在我们跳脱出程序员的框架,假设我们是一个产品经理或者说从用户的角度,我们再思考一下这个问题。
首先,需要明确一点的是,表单提交(或者说信息填写)对于用户来说是烦人的,这点从你每次填问卷星时的心情就能看出。那表单要如何改善这个填写体验呢?
答案仍是内建功能,像自动补全、自动校验等功能都是浏览器提供给表单的功能,如果你单列每个元素,再使用自己定义的数据结构进行集合和提交,就无法调用这些浏览器功能,这是表单独一无二的体验(与浏览器功能深度绑定),而不仅仅是免去了重复造轮子这么简单。
对于浏览器(底层实现)而言,表单为信息收集提供了统一的标准和接口,有助于其对该功能进行专门的优化和实现。
对于开发者而言,表单为信息收集提供了一套预定义的行为,简化了开发步骤。
对于用户而言,表单为信息填写优化了流程,自动填充等功能优化了用户体验。
HTTP中,提交数据的方式,最常用的就是GET和POST,这也对应着表单的两种提交方式。
example.com/api/user?id=123456®ion=zh-cn
POST把数据以键值对的方式放在HTML报文的Payload中,但这个方式一定是键值对吗?其实不然。我们参考W3C文档发现提交表单会经历如下步骤:
name
属性,即所谓的successful controls)action
指定的url从上面的步骤中我们可以清楚地看到,在第三步中我们可以修改编码类型,对应表单的enctype
属性,而这个属性与HTTP请求头中的Content-Type
字段相对应:
application/x-www-form-urlencoded
:GET方法的默认编码,且不可修改;POST也默认为此编码,但表达当时略有不同(直接写成键值对而非Query)multipart/form-data
:一种分部二进制的编码方式,使用表单上传文件时必须使用此格式. 请求体被分割成多部分,每部分使用 --boundary分割application/json
:JSON格式,但老版本HTML原生表单并不支持这种格式,只有新版本的HTML才支持,对于不支持的格式会Fallback到默认值
name
属性)出现了复杂结构,如嵌套对象(obj[key]
)或数组(arr[0]
)这样的结构时,会自动生成对应对象,其中缺失的数组序号会用null
替代一个使用JSON的表单例子如下:
<form enctype='application/json'>
<input name='pet[0][species]' value='Dahut'>
<input name='pet[0][name]' value='Hypatia'>
<input name='pet[1][species]' value='Felis Stultus'>
<input name='pet[1][name]' value='Billie'>
</form>
其生成的JSON如下:
{
"pet": [
{
"species": "Dahut",
"name": "Hypatia"
},
{
"species": "Felis Stultus",
"name": "Billie"
}
]
}
这里以Antd1.x+Vue2为背景介绍组件库中的表单概念,与HTML表单的区别与共性,以及具体使用方法。不同的组件库的表单设计思路可能略有不同(如mui和antd),不同框架对表单的操作模式也不同,但总体设计思路都是大同小异的。
antd中的表单和表单项都使用antd的Grid布局(24等分的flex布局)。
在使用表单时需要用this.form = this.$form.createForm(this, [options])
进行绑定(或者说包装)
Form.create()
包装过的组件会自带 this.form
属性,即可以直接在组件的this
中获取表单的属性和方法getFieldsXXX(args)
方法可以获取表单中控件的值,args用于指定控件,留空则获取所有this.form.validateFields(values, err)
进行表单校验并获取表单值v-decorator
指令进行表单绑定而不是name
*属性作者: ChlorineC
创建于: 2023-05-31 15:20:00
更新于: 2025-01-11 21:00:00
版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
本文介绍了前端开发中网络基础的关键概念,包括HTTP状态码与REST API的关系、TCP/IP协议的三次握手与四次挥手、DNS和DHCP协议、用户状态校验、常见网络攻击及其防范、HTTPS协议及其加密算法、HTTP/2.0的特性以及WebSocket协议的应用。重点强调了安全性和性能优化的重要性。
EDM(电子直邮营销)是一种通过电子邮件向特定受众发送商业信息的营销方式,具有独特的HTML编写要求,如兼容性问题和使用<table>布局。EDM编写需遵循特定规则,如使用内联样式和独立代码处理移动端与桌面端。文中还探讨了EDM编写过程中的可读性和维护性问题,并提出了建立EDM框架的建议,以提高代码的可维护性和可读性,强调组件复用和样式管理的重要性。
作者分享了个人博客框架迭代历程:从Hexo迁移到Astro的尝试,到发现Elog平台带来的启发,最终思考将Notion作为内容管理系统的新方案。文章重点描述了作者对博客系统的核心需求——解决创作同步问题,以及在探索NotionNext等解决方案过程中遇到的技术限制和思考。
前端模块化的演变包括CJS、AMD、CMD、UMD和ESM,现代浏览器支持ESM,webpack负责模块处理和打包,确保在浏览器中高效运行模块,支持代码拆分和Tree Shaking以优化性能。