学习目标:
通过简单的实践,学习基本的 HTML FORM 标签,理解各种表单元素的使用场景,并且掌握表单一系列基本验证方式。
学习内容:
1.HTML表单
HTML 表单用于搜集不同类型的用户输入。
(1)<form>元素
HTML 表单用于收集用户输入。
<form>元素定义 HTML 表单:
<form>
...
form elements
...
</form>
表单元素指的是不同类型的 input 元素、复选框、单选按钮、提交按钮等等。
(2)<input> 元素
<input> 元素是最重要的表单元素。
<input> 元素有很多形态,根据不同的 type 属性。
文本输入
<input type=“text”> 定义用于文本输入的单行输入字段:
<form>
First name:<br>
<input type="text" name="firstname">
<br>
Last name:<br>
<input type="text" name="lastname">
</form>
单选按钮输入
<input type=“radio”> 定义单选按钮。
单选按钮允许用户在有限数量的选项中选择其中之一:
<form>
<input type="radio" name="sex" value="male" checked>Male
<br>
<input type="radio" name="sex" value="female">Female
</form>
提交按钮
<input type=“submit”> 定义用于向表单处理程序(form-handler)提交表单的按钮。
表单处理程序通常是包含用来处理输入数据的脚本的服务器页面。
表单处理程序在表单的 action 属性中指定:
<form action="action_page.php">
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit">
</form>
(3)Action 属性
action包含一个地址,该地址定义了表单信息将被发送到哪里
action 属性定义在提交表单时执行的动作。
向服务器提交表单的通常做法是使用提交按钮。
通常,表单会被提交到 web 服务器上的网页。
在上面的例子中,指定了某个服务器脚本来处理被提交表单:
<form action="action_page.php">
如果省略 action 属性,则 action 会被设置为当前页面。
(4)Method 属性
method可以是 GET 或 POST 并定义表单信息的发送方式
method 属性规定在提交表单时所用的 HTTP 方法(GET 或 POST):
<form action="action_page.php" method="GET">
<form action="action_page.php" method="POST">
何时使用GET?
您能够使用 GET(默认方法):
如果表单提交是被动的(比如搜索引擎查询),并且没有敏感信息。
当您使用 GET 时,表单数据在页面地址栏中是可见的:
action_page.php?firstname=Mickey&lastname=Mouse
注释
:GET 最适合少量数据的提交。浏览器会设定容量限制。
何时使用POST?
您应该使用 POST:
如果表单正在更新数据,或者包含敏感信息(例如密码)。
POST 的安全性更好,因为在页面地址栏中被提交的数据是不可见的。
(5)Name 属性
如果要正确地被提交,每个输入字段必须设置一个 name 属性。
<form action="action_page.php">
First name:<br>
<input type="text" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit">
</form>
本例只会提交 “Last name” 输入字段
(6)用 <fieldset> 组合表单数据
<fieldset> 元素组合表单中的相关数据
<legend> 元素为 <fieldset> 元素定义标题。
<form action="action_page.php">
<fieldset>
<legend>Personal information:</legend>
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br><br>
<input type="submit" value="Submit"></fieldset>
</form>
(7)HTML Form 属性
补充知识:
2.使用内置表单数据校验
HTML5一个特别有用的新功能就是,可以在不写一行脚本代码的情况下,即对用户的输入进行数据校验,这都是通过表单元素的校验属性实现的,这些属性可以让你定义一些规则,用于限定用户的输入,比如某个输入框是否必须输入,或者某个输入框的字符串的最小最大长度限制,或者某个输入框必须输入一个数字、邮箱地址等;还有数据必须匹配的模式。如果表单中输入的数据都符合这些限定规则,那么表示这个表单校验通过,否则则认为校验未通过。
当一个元素校验通过时:
- 该元素将可以通过 CSS 伪类 :valid 进行特殊的样式化;
- 如果用户尝试提交表单,如果没有其它的控制来阻止该操作(比如JavaScript即可阻止提交),那么该表单的数据会被提交。
如果一个元素未校验通过:
- 该元素将可以通过 CSS 伪类 :invalid 进行特殊的样式化;
- 如果用户尝试提交表单,浏览器会展示出错误消息,并停止表单的提交。
(1)required 属性
最简单的HTML5校验功能是 required属性 — 如果要使输入成为必需的,则可以使用此属性标记元素。 当设置此属性时,如果输入为空,该表单将不会提交(并将显示错误消息),输入也将被视为无效。
添加一个 required 属性到你的 input 元素, 如下所示
<form>
<label for="choose">Would you prefer a banana or cherry?</label>
<input id="choose" name="i_like" required>
<button>Submit</button>
</form>
input:invalid {
border: 2px dashed red;
}
input:valid {
border: 2px solid black;
}
(2)使用正则表达式校验
另一个常用的校验功能是 pattern 属性, 以 Regular Expression 作为 value 值. 正则表达式 (regex) 是一个可以用来匹配文本字符串中字符的组合的模式,所以它们是理想的表单校验器,也可以支持 JavaScript 中许多其它的用途。
(3)限制输入的长度
所有文本框 (<input> 或 <textarea>) 都可以使用minlength和maxlength 属性来限制长度. 如果输入的字段长度小于 minlength 的值或大于 maxlength 值则无效. 浏览器通常不会让用户在文本字段中键入比预期更长的值,不过更精细的设置总归是更好的。
在数字条目中 (i.e.<input type=“number”>), 该 min 和 max 属性同样提供校验约束.如果字段的值小于min 属性的值或大于 max 属性的值,该字段则无效.
(4)自定义错误信息
每次我们提交无效的表单数据时, 浏览器总会显示错误信息. 但是显示的信息取决于你所使用的浏览器。
这些自动生成的错误有两个缺点:
- 没有标准可以让 CSS 来改变他们的界面外观.
- 这依赖于他们使用的浏览器环境, 意味着你可能在这种语言的页面里得到另一种语言的错误提示.
3.正则表达式
正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、matchAll、replace、search 和 split 方法。本文介绍 JavaScript 正则表达式。
(1)创建一个正则表达式
你可以使用以下两种方法构建一个正则表达式:
使用一个正则表达式字面量,其由包含在斜杠之间的模式组成,如下所示:
var re = /ab+c/;
脚本加载后,正则表达式字面量就会被编译。当正则表达式保持不变时,使用此方法可获得更好的性能。
或者调用RegExp对象的构造函数,如下所示:
var re = new RegExp("ab+c");
在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。
(2)编写一个正则表达式的模式
一个正则表达式模式是由简单的字符所构成的,比如 /abc/;或者是简单和特殊字符的组合,比如 /ab
c/ 或 /Chapter (\d+).\d
/。最后的例子中用到了括号,它在正则表达式中常用作记忆设备。即这部分所匹配的字符将会被记住以备后续使用。
使用简单模式
简单模式是由你想直接找到的字符构成。比如,/abc/ 这个模式就能且仅能匹配 “abc” 字符按照顺序同时出现的情况。例如在 “Hi, do you know your abc’s?” 和 “The latest airplane designs evolved from slabcraft.” 中会匹配成功。在上述两个例子中,匹配的子字符串是 “abc”。但是在 “Grab crab” 中会匹配失败,因为它虽然包含子字符串 “ab c”,但并不是准确的 “abc”。
使用特殊字符
当你需要匹配一个不确定的字符串时,比如寻找一个或多个 “b”,或者寻找空格,可以在模式中使用特殊字符。比如,你可以使用 /ab
c/ 去匹配一个单独的 “a” 后面跟了零个或者多个 “b”,同时后面跟着 “c” 的字符串:
的意思是前一项出现零次或者多次。在字符串 “cbbabbbbcdebc” 中,这个模式匹配了子字符串 “abbbbc”。
Escaping
如果你需要使用任何特殊字符的字面值(例如,搜索字符’
’),你必须通过在它前面放一个反斜杠来转义它。 例如,要搜索’a’后跟’
‘后跟’b’,你应该使用/a*b/- 反斜杠“转义”字符’
’,使其成为文字而非特殊符号。
类似地,如果您正在编写正则表达式文字并且需要匹配斜杠(’/’),那么需要转义它(否则,斜杠是正则终止符)。 例如,要搜索字符串“/ example /”后跟一个或多个字母字符,您需要使用//example/[a-z]+/i——每个斜杠之前使用反斜杠使它们成为普通字符。
要匹配文本符号反斜杠,您需要转义反斜杠。 例如,要匹配字符串“C:\”,其中“C”可以是任何字母,您将使用/[A-Z]:\/ —— 第一个反斜杠转义后面的那个反斜杠,因此表达式搜索单个普通字符反斜杠。
如果将RegExp构造函数与字符串文字一起使用,请记住反斜杠是字符串文字中的转义,因此要在正则表达式中使用它,您需要在字符串文字级别转义它。 /a*b/ 和new RegExp(“a\
b”)创建的表达式是相同的,搜索“a”后跟文字“
”后跟“b”。
使用插入语
任何正则表达式的插入语都会使这部分匹配的副字符串被记忆。一旦被记忆,这个副字符串就可以被调用于其它用途,如同 使用括号的子字符串匹配之中所述。
比如, /Chapter (\d+).\d
/ 解释了额外转义的和特殊的字符,并说明了这部分pattern应该被记忆。它精确地匹配后面跟着一个以上数字字符的字符 ‘Chapter ’ (\d 意为任何数字字符,+ 意为1次以上),跟着一个小数点(在这个字符中本身也是一个特殊字符;小数点前的 \ 意味着这个pattern必须寻找字面字符 ‘.’),跟着任何数字字符0次以上。 (\d 意为数字字符, * 意为0次以上)。另外,插入语也用来记忆第一个匹配的数字字符。
括号中的”?:”,这种模式匹配的子字符串将不会被记住。比如,(?:\d+)匹配一次或多次数字字符,但是不能记住匹配的字符。
(3)使用正则表达式
当你想要知道在一个字符串中的一个匹配是否被找到,你可以使用 test 或 search 方法;想得到更多的信息(但是比较慢)则可以使用 exec 或 match 方法。如果你使用exec 或 match 方法并且匹配成功了,那么这些方法将返回一个数组并且更新相关的正则表达式对象的属性和预定义的正则表达式对象(详见下)。如果匹配失败,那么 exec 方法返回 null(也就是false)。
在接下来的例子中,脚本将使用exec方法在一个字符串中查找一个匹配。
var myRe = /d(b+)d/g;
var myArray = myRe.exec("cdbbdbsbz");
如果你不需要访问正则表达式的属性,这个脚本通过另一个方法来创建myArray:
var myArray = /d(b+)d/g.exec("cdbbdbsbz");
// 和 "cdbbdbsbz".match(/d(b+)d/g); 相似。
// 但是 "cdbbdbsbz".match(/d(b+)d/g) 输出数组 [ "dbbd" ],
// 而 /d(b+)d/g.exec('cdbbdbsbz') 输出数组 [ "dbbd", "bb", index: 1, input: "cdbbdbsbz" ].
如果你想通过一个字符串构建正则表达式,那么这个脚本还有另一种方法:
var myRe = new RegExp("d(b+)d", "g");
var myArray = myRe.exec("cdbbdbsbz");
使用括号的子字符串匹配
一个正则表达式模式使用括号,将导致相应的子匹配被记住。例如,/a(b)c /可以匹配字符串“abc”,并且记得“b”。回调这些括号中匹配的子串,使用数组元素[1],……[n]。
使用括号匹配的子字符串的数量是无限的。返回的数组中保存所有被发现的子匹配。下面的例子说明了如何使用括号的子字符串匹配。
下面的脚本使用replace()方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$ 1,$ 2表示第一个和第二个括号的子字符串匹配。
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr);
通过标志进行高级搜索
正则表达式有六个可选参数 (flags) 允许全局和不分大小写搜索等。这些参数既可以单独使用也能以任意顺序一起使用, 并且被包含在正则表达式实例中。
学习产出:
页面效果图
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Rubik" rel="stylesheet">
<title>Forms Review</title>
</head>
<body>
<section id="overlay">
<p id="logo">Order your milktea!</p>
<hr>
<!--在这里进行您的代码编写-->
<form action="submission.html" method="post">
<label for="flavor">
你想要什么口味的奶茶?
<input type="text" id="flavor" required minlength="2" maxlength="10">
</label>
<hr style="width:100px;" size=1>
<label for="many">
你想要几杯?
<input type="number" id="many" required pattern="^1([23578])\d{9}$" min="1" max="4">
</label>
<hr style="width:100px;" size=1>
<label>你需要的糖分量</label><br>
<label for="sweet">
无糖<input type="range" id="sweet">全糖
</label>
<hr style="width:100px;" size=1>
<label>你想要什么顶料?</label><br>
<label>
<input type="checkbox">冰淇淋
</label>
<label>
<input type="checkbox">奶盖
</label>
<label>
<input type="checkbox">可可粉
</label>
<hr style="width:100px;" size=1>
<label>你需要加冰吗?</label><br>
<label>
<input type="radio" name="ice">Yes
</label>
<label>
<input type="radio" name="ice">No
</label><br>
<hr style="width:100px;" size=1>
<label>你需要加什么料</label>
<select>
<option>珍珠</option>
<option>波霸</option>
<option>布丁</option>
</select>
<hr style="width:100px;" size=1>
<label for="scale">你要什么规格</label>
<input type="text" id="scale" name="fruit" list="l1" required pattern="大杯|小杯|中杯">
<datalist id="l1">
<option>小杯</option>
<option>中杯</option>
<option>大杯</option>
</datalist>
<hr style="width:100px;" size=1>
<label>您还有什么别的要求吗<br>
<textarea cols="40" rows="3"></textarea>
</label>
<hr style="width:100px;" size=1>
<label for="MobileTelephone">您的联系方式
<input placeholder="请输入联系电话" type="text" maxlength="11" id="MobileTelephone" name="MobileTelephone" pattern="(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$" />
</label>
<hr style="width:100px;" size=1>
<button>submit</button>
</form>
</section>
</body>
</html>
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css">
<link href="https://fonts.googleapis.com/css?family=Rubik" rel="stylesheet">
<title>Forms Review</title>
</head>
<body>
<section id="overlay">
<p class="done">Thanks for your submission!</p>
<hr>
<h1 class="tip">your food is coming soon... </h1>
</section>
</body>
</html>
body {
font-family: Rubik, Arial;
}
form {
text-align: center;
line-height: 30px;
height: 80%;
overflow: auto;
}
form hr {
width: 15%;
}
h1 {
text-align: center;
}
#overlay {
width: 80%;
margin: 3% auto;
height: 95vh;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 40px;
border:1px solid black;
max-width: 600px;
}
#overlay .done{
height: 100px;
display: block;
margin: auto;
line-height: 100px;
text-align: center;
font-weight: bolder;
font-size: 2em;
}
#logo {
height: 100px;
display: block;
margin: auto;
line-height: 100px;
text-align: center;
font-weight: bolder;
font-size: 2.5em;
}
label {
margin-right: 25px;
}