表单验证
现代网站需要大量信息才能按预期运行。像用户名、密码、“好友”、“点赞”、信用卡信息和购物订单这些信息,都是通过前端由用户提供的,然后发送到 Web 应用的服务器进行处理。这些信息用于为用户创建个性化的体验。
用户信息通常是通过 HTML 表单收集的。如果你曾在某个网站上输入过文本、从列表中选择选项、勾选复选框,然后按下回车键或点击按钮,那你很可能就填写并提交了一个 HTML 表单!
为了让通过表单提交的数据真正有用,确保信息的有效性是至关重要的——比如如果你在填写地址时误填了姓氏,那么包裹可能永远也送不到你手中!
检查表单中提交的信息是否符合预期的过程,就被称为表单验证(form validation)。在本课中,我们将探讨验证表单输入的不同技术。
为什么要验证表单
大多数数据在提交后,都会被网站或 Web 应用存储起来。这些数据会保存在服务器端的数据库中。我们有一些重要的理由来确保这些被存储进数据库的信息是准确的。
我们希望依赖这些数据的操作能正常运行:
如果允许用户输入格式错误的邮箱地址(无论是有意还是无意),我们就无法在之后联系到这个用户。
如果允许用户注册一个已被使用的用户名,可能会导致后续系统中出现各种错误。
因此,确保我们收集了所有必要的数据,并且这些数据格式是正确的,可以为 Web 应用和用户节省大量麻烦。
我们希望确保网站安全:
未经过保护的数据,会为恶意攻击者留下可乘之机,可能危害我们的应用或用户。
如果允许用户提交一个不安全的密码,那他们的账户将无法得到妥善保护。
如果表单未加保护,攻击者还可以通过表单提交一些代码片段,将其注入到我们的服务器中。
这可能会导致用户的敏感信息泄露,甚至攻击者可能获取对我们网站的控制权或破坏现有的数据!
因此,验证表单不只是为了数据规范,也是保障功能正常和防范安全风险的必要手段。
正则表达式
通过表单提交的数据通常以字符串的形式存储。字符串是计算机科学中的一种基本数据类型,它表示一系列“连接”在一起的字符。作为人类,我们可以凭直觉识别字符串中的模式,这使我们能够发现错误。试着看看下面的例子中哪里出了问题:
ABCDEF2GHIJKLMNOPQRSTUVWXYZ
My zip code is 9021
The ct meowed
<h1> Hello, World! </h2>
- 第一个例子中,本来是按照顺序排列的字母,却被一个不该出现的 2 打断了。
- 第二个例子里,著名的邮政编码本应是五位数,但只写了前四位。
- 第三个例子中,单词 "cat" 少了一个 a。
- 最后一个例子用了一个
<h1>的开始标签,但却用了不匹配的</h2>作为结束标签。
如果你能看出这些错误,是因为你的大脑已经习惯了在特定类型的数据中预期特定的模式。
但和人类不同的是,计算机无法像我们一样通过长期经验来“学习”这些模式,而是需要通过明确的编程来识别它们。为了告诉计算机要识别哪些模式,我们使用一种特殊的语言,叫做正则表达式(也称为 regex 或 regexp)。
正则表达式是一串字符,代表一种匹配模式。我们可以用这个模式来:
- 匹配整个字符串,
- 匹配字符串中的某些部分,
- 检查数据是否符合特定的格式,
- 甚至将字符串中的某部分替换成别的字符。
正则表达式是实现自动化表单验证的强大工具。
客户端验证:html
我们用来验证表单数据的第一种技术是阻止有问题的输入在一开始就被提交。这种方式被称为客户端验证(client-side validation) 。
“客户端”是代表用户与服务器进行交互的过程——对于网站来说,网页浏览器就是客户端。用于验证表单的逻辑代码会和显示表单的代码一起加载到用户的设备上,不需要和后端服务器进行任何交互就能完成验证。
由于表单验证是非常常见的需求,现代 HTML 已经内置了一些验证功能。例如,我们可以用 HTML 来让表单中的某些字段必填,而其他字段为可选。我们还可以用 HTML 设置输入字段的最小值或最大值,或是文本输入的最短和最长长度。甚至可以要求输入的内容符合特定格式的模式,这个模式可以通过正则表达式来定义。
如果用户输入的内容不符合 HTML 表单验证中定义的规则,表单将无法提交,而且用户会收到一个错误提示信息,说明哪里出了问题。
使用这些检查手段,可以减少后端接收到错误数据的可能性。HTML 表单验证也对用户有益处 —— 因为验证是在客户端直接进行的,用户能立即得到反馈,不需要等待与后端耗时的通信过程。
html自带的验证:
<form action="" method="POST">
<label for="text">Enter your name here:</label>
<input id="name" name="name" type="text" required minlength="3" maxlength="100">
<br><br>
<label for="number">Enter your age here:</label>
<input type="number" name="age" id="age" required min="1" max="123">
<br><br>
<label for="code">Best place to learn to code: (hint: starts with a "C")</label>
<input id="code" name="code" type="text" required pattern="[cC]odecademy">
<br><br>
<input type="submit" value="Submit">
</form>
提供的 HTML 表单中有三个必填的输入字段。尝试在缺少其中任意一个的情况下提交表单。你会注意到现在表单上会出现一条消息。我们并没有自己设计这个提示,它是 HTML 内置的功能。
每个输入字段还有额外的要求:
- “name” 输入框要求输入文本,长度必须在 3 到 100 个字符之间。
- “age” 输入框要求输入一个 数值,范围在 1 到 123 之间。
- “code” 输入框要求输入的内容必须是 “Codecademy” 或 “codecademy” 。
客户端验证
客户端验证有两个主要优点:
首先,用户体验更好:用户能立即收到不合法输入的提示,而不需要等服务器返回结果再重新填写表单。
其次,可以节省应用程序的时间和资源:越早发现错误,就越能减少后续处理的成本。
不过,并不是所有问题都可以通过 HTML 内置验证解决。
为了实现更复杂或更定制化的验证,我们可以加入 JavaScript 来对表单进行验证。这可以通过自己编写 JavaScript 代码来实现,也可以通过引入 JavaScript 验证库来完成。例如,如果我们的网站对用户名有特殊要求,那就需要自己实现相应的验证逻辑。
如果我们做的是一个相对简单的网站,自己手写验证代码或者使用一个简单的纯 JavaScript 库(比如 just-validate)是合理的选择。但大多数基础验证库都需要直接访问或操作 DOM,而这在使用一些依赖虚拟 DOM 的框架(例如 React 或 Vue)时可能变得复杂。
在这种情况下,最好使用适配你所使用框架的表单验证库。例如,formik 是一个轻量级的库,它可以简化 React 应用中的表单验证流程。
后端验证
无论一个网站或应用的前端验证看起来多么完善,仍然必须在后端(也称为服务器端)进行验证。前端验证非常容易被绕过——比如,一个恶意用户只需关闭浏览器中的 JavaScript 功能就可以跳过验证。此外,还存在“中间人攻击”的风险,即用户提交请求后,在数据到达服务器之前被篡改。作为一条基本准则,后端永远不应该轻信它收到的数据。
幸运的是,作为开发者,一旦数据到了后端,我们就拥有对其的完全控制。后端验证有以下几个优势:
- 可以利用计算能力更强的服务器来运行验证代码。
- 验证逻辑对用户是不可见的——如果恶意用户看不到验证规则,他们就更难找到绕过方法。
- 可以与前端无法访问的数据进行比对,例如检查数据库中某个用户名是否已被注册。
后端验证通常有两种方式:
- 用户仍在填写表单时进行验证:我们可以向服务器发起异步请求(如 AJAX),发送部分数据并直接返回验证反馈。这种方式比前端验证慢一些,而且在用户体验设计上会更具挑战。
- 用户提交表单后进行验证:这是整个应用对不良数据的最后一道防线。在数据被写入数据库之前,验证其有效性和安全性至关重要。此阶段我们还可以进行**“数据清洗(sanitize)”**:为了保持数据库中数据的一致性,我们通常希望将用户的输入统一转换成一种标准格式,即使在输入时格式比较宽松。
总结
-
现代网站需要从用户那里获取大量信息,而这些信息大多是通过 HTML 表单收集的。
-
验证通过表单提交的数据至关重要,它不仅可以确保网站的安全性,还能保证网站正常运行。
-
正则表达式是一种用于定义文本模式的字符序列,是验证输入时的重要工具。
-
现代 HTML 提供了许多实用的内建表单验证方法。
-
使用 JavaScript 可以实现自定义且复杂的客户端验证逻辑。
-
可以通过向服务器发送异步请求,在用户提交表单前执行后端验证。
-
最终的后端验证是确保应用安全性并清洗所有数据的必要步骤。
html表单
表单是我们日常生活的一部分。当我们在现实生活中填写一张纸质表单时,我们会将信息写下来,然后交给某人处理。想想你填写求职申请、银行开户申请,或者投递意见卡的经历——这些都是表单的实例!
与纸质表单类似,HTML 的 <form> 元素负责收集信息并将其发送到其他地方。每次我们浏览网页时,其实都在接触各种表单,只是我们可能没有察觉。如果你正在某个文本框中输入内容或者提供某种输入,很有可能你正在使用一个 <form> 表单中的字段!
在本课中,我们将学习 <form> 的结构和语法,以及用于填充表单的各种元素。
表单是如何工作的
我们可以将互联网看作是一个计算机网络,计算机在其中发送和接收信息。计算机需要 HTTP 请求来确定如何进行通信。HTTP 请求指示接收计算机如何处理传入的信息。更多信息可以在我们关于 HTTP 请求的文章中找到。
<form> 元素是一个收集信息的好工具,但随后我们需要将这些信息发送到其他地方进行处理。我们需要为 <form> 元素提供目标位置(即信息发送到哪里)以及需要使用的 HTTP 请求类型。请看下面的示例 <form>:
<form action="/example.html" method="POST">
</form>
在上面的示例中,我们创建了一个 <form> 的框架,这个表单会以 POST 请求将信息发送到 example.html:
action属性决定了信息发送到哪里。method属性指定了一个 HTTP 动词,它将包含在 HTTP 请求中。
注意:HTTP 动词如 POST 并不需要大写才能正常工作,但通常会大写。在上面的示例中,我们也可以写成 method="post",它依然能正常工作。
<form> 元素还可以包含子元素。例如,添加一个标题对用户来说会很有帮助,用户可以知道这个表单是做什么的。我们也可以添加段落提供更多细节。以下是一个代码示例:
<form action="/example.html" method="POST">
<h1>创建一个表单</h1>
<p>看起来你想学习如何创建 HTML 表单。最好的方法就是亲自尝试。</p>
</form>
上面的示例并没有收集任何用户输入,但我们将在下一个练习中进行操作。
get 和 post的区别
| 对比点 | GET 方法 | POST 方法 |
|---|---|---|
| 用途 | 获取数据(一般用于查询) | 提交数据(如表单、注册信息等) |
| 数据发送方式 | 数据附加在 URL 后面(如:/search?q=chatgpt) | 数据放在请求体中,用户看不到 |
| 数据大小限制 | 有限制(一般为 2048 字符) | 相对没有限制(受浏览器和服务器限制) |
| 安全性 | 不安全,容易被篡改(比如在地址栏里看到密码) | 更安全一些,适合敏感信息 |
| 是否缓存 | 浏览器可能缓存 | 一般不会缓存 |
使用get时:
<form action="/search" method="GET">
<label for="query">搜索:</label>
<input type="text" id="query" name="q">
<button type="submit">提交</button>
</form>
当用户提交这个表单时,浏览器会跳转到类似这样的 URL:
/search?q=你输入的内容
文本输入
如果我们想在 <form> 表单中创建一个输入字段,我们就需要用到 <input> 元素。
<input> 元素有一个 type 属性,它决定了该元素在网页上的渲染方式以及它可以接受的数据类型。
我们要学习的第一个 type 属性的值是 "text"。当我们创建一个 type="text" 的 <input> 元素时,它会在页面上渲染为一个文本框,供用户输入内容。注意:type 的默认值就是 "text"。
此外,我们还必须为 <input> 元素添加 name 属性 —— 如果没有这个属性,用户在 <input> 中输入的信息在表单提交时不会被发送。我们会在之后的练习中更详细地讲解提交按钮和表单提交的过程。
现在,让我们看看下面这段会生成一个文本输入框的代码:
<form action="/example.html" method="POST">
<input type="text" name="first-text-field">
</form>
下面是这段代码在 Chrome 浏览器中渲染出的表单截图(不同浏览器可能略有差异):
当页面初次加载时,这个 <input> 是一个空白框。
当用户在 <input> 元素中输入内容后,value 属性的值就变成了用户输入的内容。
这个 value 的值会与 name 属性的值成对组合,在表单提交时作为文本一起发送出去。
例如,如果用户在我们的 <input> 文本框中输入了 "important details":
表单提交时,发送到 /example.html 的数据是:
first-text-field=important details
因为 name 属性的值是 "first-text-field",而 value 属性的值是 "important details"。
我们也可以为 value 属性设置默认值,让用户初次看到表单时,文本框中就已经填好了一些内容,例如:
<form action="/example.html" method="POST">
<input type="text" name="first-text-field" value="already pre-filled">
</form>
渲染出来的是:
name和id的区别
id:用来唯一标识页面上的一个元素
-
页面中每个
id必须是唯一的,不能重复。 -
常用来 关联
<label>和表单控件(通过<label for="some-id">)。 -
也用于 JavaScript、CSS 定位 一个具体的元素。
name:用来指定表单提交时的键名
-
在表单提交的时候,
name的值会作为键,控件的内容作为值一起发送。 -
一个表单控件如果没有
name,它的值不会被提交!
添加标签
在上一个练习中,我们创建了一个 <input> 元素,但并没有包含任何说明,来告诉用户这个 <input> 是做什么用的。为了让用户能够正确识别每一个 <input>,我们可以使用一个恰如其名的元素:<label> 标签。
<label> 元素有一个开始标签和一个结束标签,并显示它们之间的文本内容。
要把 <label> 和对应的 <input> 关联起来,<input> 需要一个 id 属性。接着,我们将 <label> 元素的 for 属性设置为这个 <input> 的 id 值,例如:
<form action="/example.html" method="POST">
<label for="meal">What do you want to eat?</label>
<br>
<input type="text" name="food" id="meal">
</form>
代码渲染后:
看,现在用户就能明白这个 <input> 是干嘛的
使用 <label> 元素还有一个好处:当用户点击这个标签时,关联的 <input> 会被选中或获得焦点,提升用户体验。
密码输入
想想我们每次在 <form> 表单中输入敏感信息,比如密码或 PIN 码的时候。我们当然不希望身后有人偷窥到我们的信息!幸运的是,我们可以给 <input> 元素添加 type="password" 属性!
<input type="password"> 元素会用其他字符(比如星号 * 或圆点 •)来替换用户输入的文本。以下是一个创建密码输入框的示例代码:
<form>
<label for="user-password">Password: </label>
<input type="password" id="user-password" name="user-password">
</form>
当用户在输入框中输入内容时,看起来会是这样:
一个表单中的密码输入框,显示 6 个圆点,表示输入的文本
尽管密码输入框会隐藏密码文本,但在表单提交时,输入的真实内容仍然会被发送。换句话说,如果用户输入的是 “hunter2”,那么提交时发送的数据将是:
user-password=hunter2,它会和表单中的其他信息一起发送出去。
数字输入
我们已经学习了两个和文本相关的 <input> 的 type 属性。但有时候,我们可能希望用户输入一个数字 —— 这时候我们可以将 type 属性设置为“number”!
通过为 <input> 设置 type="number",我们可以限制用户只能在输入框中输入数字(以及一些特殊字符,如 -、+ 和 .)。我们还可以添加一个 step 属性,它会在输入框中显示箭头按钮,用户可以点击这些箭头按 step 值增减数字。下面是一个用于输入数字的示例代码:
<form>
<label for="years"> Years of experience: </label>
<input id="years" name="years" type="number" step="1">
</form>
它会渲染出这样的效果:
输入范围
使用 <input type="number"> 非常适合在我们希望用户可以输入任意数字的情况下。但如果我们想限制用户可以输入的数字范围,也许可以考虑使用不同的 type 值。另一种选择是将 type 设置为 "range",这样就可以创建一个滑块控件。
**要设置滑块的最小值和最大值,我们可以为 <input> 元素的 min 和 max 属性赋值。**我们还可以通过为 step 属性赋值来控制滑块的移动流畅度。较小的 step 值会让滑块移动得更顺滑,而较大的 step 值则会让滑块移动得更明显。来看一个创建滑块的示例代码:
<form>
<label for="volume"> Volume Control</label>
<input id="volume" name="volume" type="range" min="0" max="100" step="1">
</form>
以上代码会渲染出一个音量控制的滑块。
在这个例子中,每次滑块移动一个单位,<input> 元素的 value 属性值都会随之变化。
复选框输入
<form>
<p>Choose your pizza toppings:</p>
<label for="cheese">Extra cheese</label>
<input id="cheese" name="topping" type="checkbox" value="cheese">
<br>
<label for="pepperoni">Pepperoni</label>
<input id="pepperoni" name="topping" type="checkbox" value="pepperoni">
<br>
<label for="anchovy">Anchovy</label>
<input id="anchovy" name="topping" type="checkbox" value="anchovy">
</form>
呈现效果:一个 HTML 表单,提示用户选择披萨配料,并列出了三种配料,每项配料对应一个复选框。
请注意这个示例中的几点:
- 每个复选框都设置了
value属性的值。这个值在表单上是不可见的,因此我们需要通过<label>标签来标识每个复选框的含义。 - 每个
<input>的name属性值相同。这种做法将这些复选框归为一组。然而,每个<input>都有唯一的id,用于与对应的<label>匹配。
复选框的value
value是复选框<input type="checkbox">的一个属性,它表示 当用户勾选这个复选框并提交表单时,提交的值是什么。
比如:
<input type="checkbox" name="topping" value="cheese">
如果用户勾选了这个复选框,表单提交时,后台就会收到一条数据:
topping=cheese
虽然我们给复选框设置了提交时的值(value),但用户在页面上是看不到这个值的。为了让用户知道这个复选框的含义,我们用 <label> 来展示文字说明。
单选按钮
如果我们想让用户从多个选项中选择一个或多个,复选框(checkboxes)是很好的选择。然而,在某些情况下,我们希望展示多个选项,但只允许用户选择其中一个 —— 比如询问用户是否同意条款和条件。这种时候就可以使用单选按钮(radio buttons)。我们来看一下创建单选按钮的代码:
<form>
<p>1 + 1 等于多少?</p>
<input type="radio" id="two" name="answer" value="2">
<label for="two">2</label>
<br>
<input type="radio" id="eleven" name="answer" value="11">
<label for="eleven">11</label>
</form>
这段代码的渲染效果是:
一个包含单选按钮的表单。
从代码中可以看出,单选按钮(就像复选框一样)不会直接显示其 value 值。我们通过关联的 <label> 来展示单选按钮的含义。为了将一组单选按钮归为一组,我们需要给它们分配相同的 name 属性,这样一组中就只能选择一个选项。
现在我们就来亲自实践一下,创建自己的单选按钮吧!
下拉列表
单选按钮(radio buttons)很适合在可见的几个选项中让用户选择一个。但想象一下,如果我们有一整列选项呢?这种情况可能会迅速变成一大堆单选按钮,难以管理。
一个更好的解决方案是使用下拉列表(dropdown list),这样可以让用户从一个有组织的列表中选择一个选项。下面是创建下拉菜单的代码:
<form>
<label for="lunch">午餐吃什么?</label>
<select id="lunch" name="lunch">
<option value="pizza">Pizza</option>
<option value="curry">Curry</option>
<option value="salad">Salad</option>
<option value="ramen">Ramen</option>
<option value="tacos">Tacos</option>
</select>
</form>
这段代码会渲染出一个下拉列表,默认显示第一个选项。
当我们点击这个包含第一个选项的区域时,整个下拉列表就会展开,显示所有的选项。
请注意,代码中我们使用的是 <select> 元素来创建下拉列表。为了填充这个列表,我们添加了多个 <option> 元素,并为每个 <option> 设置了 value 属性。默认情况下,这些选项中只能选择一个。
用户看到的文字是写在 <option> 标签之间的内容;但在 <form> 表单提交时,实际上提交的是 value 属性的值(注意:文本内容和 value 属性可能存在大小写等差异)。例如,如果用户从下拉列表中选择了 Pizza,那么提交时就会发送信息 "lunch=pizza"。
数据列表输入
即使我们已经用下拉列表很好地组织了选项,但如果选项太多,用户仍然可能需要花时间去滚动查找。这时候就可以使用 <datalist> 元素来简化这个过程。
<datalist> 通常和 <input type="text"> 一起使用。
<input> 创建一个文本输入框,用户可以在其中输入内容,而 <datalist> 会根据用户输入的内容筛选出匹配的选项。
下面是一个具体的例子:
<form>
<label for="city">理想旅游城市?</label>
<input type="text" list="cities" id="city" name="city">
<datalist id="cities">
<option value="New York City"></option>
<option value="Tokyo"></option>
<option value="Barcelona"></option>
<option value="Mexico City"></option>
<option value="Melbourne"></option>
<option value="Other"></option>
</datalist>
</form>
在上面的代码中,<input> 使用了 list 属性,并将其设置为 cities,这个值对应 <datalist> 的 id,这样这两个元素就建立了关联。
渲染后的效果是:
- 显示一个带标签的文本输入框。
- 当你点击输入框时,会出现一个下拉列表供你选择。
- 你也可以直接输入,没有匹配的选项也没关系,它会使用你输入的内容。
<select> 与 <datalist> 的区别:
| 特性 | <select> | <datalist> |
|---|---|---|
| 是否可以自定义输入 | ❌ 否 | ✅ 可以输入不在选项内的内容 |
| 支持筛选建议 | ❌ 否 | ✅ 输入时自动筛选匹配的选项 |
| 使用方式 | 直接选项 | 自由输入 + 提示建议 |
当表单提交时,提交的是 <input> 的 name 和它的 value。
也就是说,用户可以选择下拉里的某一项,也可以输入自己的内容,都会被提交。
<textarea> 元素
一个 <input> 元素设置 type="text" 时,会创建一个单行输入框,供用户填写信息。
然而,有些情况下用户需要输入更多内容,比如写一篇博客文章。
在这种情况下,我们就可以用 <textarea> 元素来代替 <input>。
<textarea> 元素用于创建一个更大的文本区域,让用户能输入更多文字。
我们可以通过设置 rows 和 cols 属性来控制 <textarea> 的行数和列数。来看下面的代码示例:
<form>
<label for="blog">新博客文章:</label>
<br>
<textarea id="blog" name="blog" rows="5" cols="30">
</textarea>
</form>
上面的代码会渲染一个空的 <textarea>,大小为 5 行 30 列,显示效果如下:
如果我们想要更大的文本输入框,可以点击并拖拽文本框右下角进行调整。
当表单被提交时,<textarea> 的值就是用户在文本框中输入的内容。
如果我们希望在 <textarea> 中默认显示一些内容,可以将该内容直接写在标签之间,比如:
<textarea>默认填写的文字</textarea>
这样渲染出的 <textarea> 会包含预填充的文本:“默认填写的文字”。
提交表单
还记得表单的主要用途是什么吗?就是收集信息并提交。
这正是**提交按钮(submit button)**的作用 —— 当用户填写完 <form> 中的信息,并准备好将其发送出去时,就会点击这个按钮。
现在我们已经学习了如何创建各种输入元素,接下来就来学习如何创建一个提交按钮!
要在 <form> 中创建一个提交按钮,我们会使用熟悉的 <input> 元素,并将其 type 设置为 "submit"。比如:
<form>
<input type="submit" value="发送">
</form>
这段代码渲染出的按钮大概是这样的:
请注意:上面代码中的 value 属性定义了按钮上显示的文字。
如果没有设置 value 属性,按钮默认会显示为“Submit”。
现在就来添加这个元素,让我们的表单更完整吧!
总结
-
<form>的目的是允许用户输入信息并提交。 -
<form>的action属性决定了表单信息将被发送到哪里。 -
<form>的method属性决定了信息如何被发送和处理。 -
要添加用户输入信息的字段,我们使用
<input>元素,并设置type属性为我们想要的字段类型:type="text":创建一个单行文本输入框。type="password":创建一个输入内容被遮挡的单行文本输入框。type="number":创建一个用于输入数字的单行输入框。type="range":创建一个可以选择数值范围的滑动条。type="checkbox":创建一个复选框,可以和其他复选框配合使用。type="radio":创建一个单选按钮,可以与其他单选按钮组合使用。type="text"并添加list属性:可以将<input>与<datalist>元素关联(list的值需和<datalist>的id相同)。type="submit":创建一个提交按钮。
-
<select>元素与多个<option>元素一起使用,渲染出一个下拉列表。 -
<datalist>元素与<option>元素一起使用,并与<input>搭配实现可搜索的选项列表。 -
<textarea>元素用于输入大量文本,并且输入区域大小可以自定义。 -
当提交
<form>时,所有接受输入的字段会以name=value的形式提交数据。
通过将 <form> 元素与上述各种元素结合使用,我们可以创建更能满足用户需求和期望的网站。