zoukankan      html  css  js  c++  java
  • 表单/验证表单——千万不要做一个只会拖控件、“照猫画虎”、copy/paste 程序员

    在用 .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="提交" />&nbsp;<input type="reset" value="重置" /></p>
        </form>
    </body>
    </html>

    运行界面:

    ODAK5G%`Z4M`@BP%V5IS%`S

    说明:

    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="提交" />&nbsp;<input type="reset" value="重置" /></p>
        </form>
    </body>
    </html>

    运行界面:

    FM5%R@DW[U]`6$$92S8}@]A

    说明:

    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>

    运行界面:

    9Y8OL8)6XQ0M3RDS8UH7J8M

    下载 Demo

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

  • 相关阅读:
    各大公司 Java 后端开发面试题总结
    java程序开发工具集的使用
    删数
    能量项链//区间DP
    合并傻子//区间dp
    P1005 采药
    表达式计算系列
    进制转换
    最长公共子序列
    乘法游戏
  • 原文地址:https://www.cnblogs.com/liuning8023/p/2199381.html
Copyright © 2011-2022 走看看