在用 .NET 开发时,随便往页面上拖几个服务器端控件,在控件事件里写点代码处理一下——表单在哪?现在,便利的 IDE 环境越来越弱化“表单”的概念,这个概念的意义更多的是作为一个术语,写在书里,或是用于程序员之间的交流(当使用这个词时,彼此都知道对方在说什么)。当我毕业参加工作时,开发 Web 应用程序已经跟传统方式有很大区别,因此,一直无法体会“表单”。
“表单”概念对 Web 应用程序一直都重要——客户端向服务器端提交(以 get/post 方式)的数据。我是用 .NET 的,.NET 将控件区分成:HTML 控件(客户端控件)和服务器端控件。前者就是传统的、Web 应用程序最初的表单控件。但在 .NET 里,我们可以向任何控件添加 "runat=server" 属性,这样它就会被发送给服务器端。
若你认为,用就行了,想那么多干嘛!我见过太多这样的人,无论是我同学,还是网上,请教问题的态度真得很好——谦虚,礼貌。可抛出的问题,充分说明,他们的基础真的很差……事实说明,千万不要做一个只会拖控件、“照猫画虎”、copy/paste 程序员。
本文演示客户端验证表单,通过后发送到服务器端。
本文内容
- 表单验证
- 示例1:注册
- 示例2:购物
- .NET 表单验证
表单验证
示例1:注册
页面完成加载后,初始化页面(表单),添加提交表单前(onsubmit),对表单验证的事件。如果验证成功,则提交;否则,不提交。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" href="css/main.css" />
<script type="text/javascript">
1: 2: window.onload = initForms; 3: 4: function initForms() {
5: for (var i = 0; i < document.forms.length; i++) {
6: document.forms[i].onsubmit = function() { return validForm(); }
7: } 8: } 9: 10: function validForm() {
11: var allGood = true;
12: var allTags = document.getElementsByTagName("*");
13: 14: for (var i = 0; i < allTags.length; i++) {
15: if (!validTag(allTags[i])) {
16: allGood = false;
17: } 18: } 19: return allGood;
20: 21: function validTag(thisTag) {
22: var outClass = "";
23: var allClasses = thisTag.className.split(" ");
24: 25: for (var j = 0; j < allClasses.length; j++) {
26: outClass += validBasedOnClass(allClasses[j]) + " ";
27: } 28: 29: thisTag.className = outClass; 30: 31: if (outClass.indexOf("invalid") > -1) {
32: invalidLabel(thisTag.parentNode); 33: thisTag.focus(); 34: if (thisTag.nodeName == "INPUT") {
35: thisTag.select(); 36: } 37: return false;
38: } 39: return true;
40: 41: function validBasedOnClass(thisClass) {
42: var classBack = "";
43: 44: switch (thisClass) {
45: case "":
46: case "invalid":
47: break;
48: case "reqd":
49: if (allGood && thisTag.value == "") classBack = "invalid ";
50: classBack += thisClass; 51: break;
52: default:
53: if (allGood && !crossCheck(thisTag, thisClass)) classBack = "invalid ";
54: classBack += thisClass; 55: } 56: return classBack;
57: } 58: 59: function crossCheck(inTag, otherFieldID) {
60: if (!document.getElementById(otherFieldID)) return false;
61: return (inTag.value == document.getElementById(otherFieldID).value);
62: } 63: 64: function invalidLabel(parentTag) {
65: if (parentTag.nodeName == "LABEL") {
66: parentTag.className += " invalid";
67: } 68: } 69: } 70: } 71: </ script > </head>
<body>
<form action="#">
<p>
<label for="userName">
名字:
<input type="text" size="30" id="userName" class="reqd" /></label></p>
<p>
<label for="passwd1">
密码:
<input type="password" id="passwd1" class="reqd" /></label></p>
<p>
<label for="passwd2">
确认密码:
<input type="password" id="passwd2" class="reqd passwd1" /></label></p>
<p>
<input type="submit" value="提交" /> <input type="reset" value="重置" /></p>
</form>
</body>
</html>
运行界面:

说明:
1,当某个字段不合法时,脚本会在 class 属性里添加 "invalid",在之后的处理中,如果一个标记的 class 属性里包含 "invalid",则改变第一个非法行的式样,并且焦点在那行的 input 标记;
2,页面里,每个标签的 class 属性用于指定表单验证时,使用的规则,用空格分隔,可以在函数 validBasedOnClass 看到。比如,class="reqd" 为应用“必填”规则;class="reqd password1" 为应用两个规则,除了必填外,该标记的值要与 ID为 "password1" 的值相等;
3,第 11 ~ 19 行,为验证的主函数。有意思的是,在这个主函数里,内嵌了几个子功能的函数,如 crossCheck、invalidLable等。在示例2,更清楚;
示例2:购物
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" href="css/main.css" />
<script type="text/javascript">
1: 2: window.onload = initForms; 3: 4: // 初始化表单
5: function initForms() {
6: // 本页只有一个form
7: for (var i = 0; i < document.forms.length; i++) {
8: document.forms[i].onsubmit = function() { return validForm(); }
9: } 10: document.getElementById("sunroof").onclick = function() {
11: if (this.checked)
12: document.getElementById("twoDoor").checked = true;
13: else
14: document.getElementById("twoDoor").checked = false;
15: } 16: }; 17: // 验证表单
18: function validForm() {
19: var allGood = true;
20: var allTags = document.getElementsByTagName("*");
21: for (var i = 0; i < allTags.length; i++) {
22: if (!validTag(allTags[i])) {
23: allGood = false;
24: } 25: } 26: return allGood;
27: 28: // 验证标记
29: function validTag(thisTag) {
30: var outClass = "";
31: var allClasses = thisTag.className.split(" ");
32: 33: for (var j = 0; j < allClasses.length; j++) {
34: outClass += validBasedOnClass(allClasses[j]) + " ";
35: } 36: 37: thisTag.className = outClass; 38: 39: if (outClass.indexOf("invalid") > -1) {
40: invalidLabel(thisTag.parentNode); 41: thisTag.focus(); 42: if (thisTag.nodeName == "INPUT") {
43: thisTag.select(); 44: } 45: return false;
46: } 47: return true;
48: 49: // 基于 class 验证
50: function validBasedOnClass(thisClass) {
51: var classBack = "";
52: 53: switch (thisClass) {
54: case "":
55: case "invalid":
56: break;
57: case "reqd":
58: if (allGood && thisTag.value == "") classBack = "invalid ";
59: classBack += thisClass; 60: break;
61: case "radio":
62: if (allGood && !radioPicked(thisTag.name)) classBack = "invalid ";
63: classBack += thisClass; 64: break;
65: case "isNum":
66: if (allGood && !isNum(thisTag.value)) classBack = "invalid ";
67: classBack += thisClass; 68: break;
69: case "isZip":
70: if (allGood && !isZip(thisTag.value)) classBack = "invalid ";
71: classBack += thisClass; 72: break;
73: case "email":
74: if (allGood && !validEmail(thisTag.value)) classBack = "invalid ";
75: classBack += thisClass; 76: break;
77: default:
78: if (allGood && !crossCheck(thisTag, thisClass)) classBack = "invalid ";
79: classBack += thisClass; 80: } 81: return classBack;
82: } 83: // 用一个字段验证另一个字段
84: function crossCheck(inTag, otherFieldID) {
85: if (!document.getElementById(otherFieldID)) return false;
86: return (inTag.value != "" || document.getElementById(otherFieldID).value != "");
87: } 88: // 单选,必须选一个
89: function radioPicked(radioName) {
90: var radioSet = "";
91: 92: for (var k = 0; k < document.forms.length; k++) {
93: if (!radioSet) {
94: radioSet = document.forms[k][radioName]; 95: } 96: } 97: if (!radioSet) return false;
98: for (k = 0; k < radioSet.length; k++) {
99: if (radioSet[k].checked) {
100: return true;
101: } 102: } 103: return false;
104: } 105: // 验证数字
106: function isNum(passedVal) {
107: var re = /\d/;
108: return re.test(passedVal);
109: } 110: // 验证邮编
111: function isZip(inZip) {
112: if (inZip == "") {
113: return true;
114: } 115: return (isNum(inZip));
116: } 117: // 正则表达式验证Email
118: function validEmail(email) {
119: var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
120: return re.test(email);
121: } 122: // 标识非法 Label
123: function invalidLabel(parentTag) {
124: if (parentTag.nodeName == "LABEL") {
125: parentTag.className += " invalid";
126: } 127: } 128: } 129: }; 130: </ script > </head>
<body>
<h2 style="text-align: center;">
挑选汽车</h2>
<form method="post" action="rec.aspx">
<p>
<label for="emailAddr">
Email地址:
<input id="emailAddr" type="text" size="30" class="reqd email" />
</label>
</p>
<hr />
<p>
<label for="color">
颜色:
<select id="color" class="reqd">
<option value="" selected="selected">选择颜色</option>
<option value="Red">红色</option>
<option value="Green">绿色</option>
<option value="Blue">蓝色</option>
</select>
</label>
</p>
<hr />
<p>
可选:
<label for="sunroof">
<input type="checkbox" id="sunroof" value="Yes" />Sunroof(只有2个门)</label>
<label for="pWindows">
<input type="checkbox" id="pWindows" value="Yes" />Power Windows</label>
</p>
<hr />
<p>
<label for="DoorCt">
门:
<input type="radio" id="twoDoor" name="DoorCt" value="twoDoor" class="radio" />2
门
<input type="radio" id="fourDoor" name="DoorCt" value="fourDoor" class="radio" />4
门
</label>
</p>
<hr />
<p>
<label for="zip">
填写邮编或选择你最近的供应商:<br />
邮编:
<input id="zip" type="text" size="5" maxlength="5" class="isZip dealerList" />
<select id="dealerList" size="4" class="zip">
<option value="California--Lemon Grove">California--Lemon Grove</option>
<option value="California--Lomita">California--Lomita</option>
<option value="California--Long Beach">California--Long Beach</option>
<option value="California--Los Alamitos">California--Los Alamitos</option>
<option value="California--Los Angeles">California--Los Angeles</option>
</select>
</label>
</p>
<hr />
<p>
<input type="submit" value="提交" /> <input type="reset" value="重置" /></p>
</form>
</body>
</html>
运行界面:
![FM5%R@DW[U]`6$$92S8}@]A FM5%R@DW[U]`6$$92S8}@]A](https://images.cnblogs.com/cnblogs_com/liuning8023/201110/20111005144458427.jpg)
说明:
1,示例2 与示例1 差不多;
2,validForm 函数里内嵌了好几个功能性函数。这点比较有意思。
1: function validForm() {
2: var allGood = true;
3: var allTags = document.getElementsByTagName("*");
4: // 调用函数 validTag
5: // ......
6: 7: return allGood;
8: 9: function validTag(thisTag) {
10: var outClass = "";
11: var allClasses = thisTag.className.split(" ");
12: // 调用函数 validBasedOnClass
13: // ......
14: for (var j = 0; j < allClasses.length; j++) {
15: outClass += validBasedOnClass(allClasses[j]) + " ";
16: } 17: 18: thisTag.className = outClass; 19: 20: if (outClass.indexOf("invalid") > -1) {
21: // 调用函数 invalidLabel
22: // ......
23: return false;
24: } 25: return true;
26: 27: function validBasedOnClass(thisClass) {
28: // 使用 all Good 和 thisTag 变量
29: // 以及调用函数 crossCheck radioPicked isNum isZip validEmail
30: // ......
31: } 32: 33: function crossCheck(inTag, otherFieldID) {
34: // ......
35: } 36: 37: function radioPicked(radioName) {
38: // ......
39: } 40: 41: function isNum(passedVal) {
42: // ......
43: } 44: 45: function isZip(inZip) {
46: // ......
47: } 48: function validEmail(email) {
49: // ......
50: } 51: // 标识非法 Label
52: function invalidLabel(parentTag) {
53: // ......
54: } 55: } 在上面的结构,内嵌函数使用了它外层的变量。比如,定义在 validForm 里的 allGood 变量,在 validBasedOnClass 里使用了。这是 JavaScript 的一个特色,可以缓存数据,你可以查匿名函数的相关资料。
.NET 表单验证
上面表单验证,比如验证Email 地址,若在 .NET 里,可以用如下简单方式:
<asp:TextBox ID="emailAddr" runat="server"></asp:TextBox><br />
<asp:RegularExpressionValidator ValidationExpression="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$"
ID="RegularExpressionValidator1" ControlToValidate="emailAddr" runat="server"
ErrorMessage="Email 地址非法"></asp:RegularExpressionValidator>
运行界面:

下载 Demo
| 本文版权归作者和博客园,欢迎转载。若要转载,请在文章注明原文出处。 |