整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript基础知识:表单的验证和关键字

JavaScript基础知识:表单的验证和关键字

s表单验证:通过document.forms['表单名'] \['元素名']

```

<!DOCTYPE html>

<html>

<head>

<title>表单验证</title>

</head>

<body>

<form name="myform" action="demo.py" onsubmit="return validateForm()" method="post">

名字:<input type="text" name="fname">

<input type="submit" value="提交">

</form>

</body>

</html>

<script type="text/javascript">

function validateForm() {

var val=document.forms['myform']['fname'].value;

if (val==''||val==null) {

alert('名字不能为空')

return false;

}

}

</script>

```

![在这里插入图片描述](https://img-blog.csdnimg.cn/20190305192743761.png)

HTML表单自动验证:表单的验证可以通过浏览器来自动完成。如果表单字段的值为空,**required**属性会阻止表单提交

```

名字:<input type="text" name="uname" required="required">

```

##### 数据验证

数据验证用来确保用户输入的数据是有效的,典型的数据验证有:

- 必须字段是否有输入

- 用户是否输入了合法数据

- 在数字字段是否输入了文本

- 验证是否是一个正确的email地址

- 日期是否输入正确

js约束验证DOM方法:

checkValidity():如果input元素中的数据是合法的返回true,否则返回false。

setCustomValidity()设置input元素的validationMessage属性,用于定义错误提示信息的方法

在js中this关键字不是固定不变的,它会随着执行环节的改变而改变,ES2015(ES6) 新增加了两个重要的 JavaScript 关键字: letconst。let 声明的变量只在 let 命令所在的代码块内有效。const 声明一个只读的常量,一旦声明,常量的值就不能改变。在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量。

const用于声明一个或多个常量,声明必须初始化,且初始化后值不可再修改。Json格式:json是一种轻量级的数据交换格式。json数据格式为键值对形式。将json字符串转换为javascript对象:使用js内置函数JSON.parse()将字符串转为javaScript对象,JSON。stringify()将JavaScript转为json字符

内容是《Web前端开发之Javascript视频》的课件,请配合大师哥《Javascript》视频课程学习。

表单校验可以确保用户以正确的格式填写表单数据,确保提交的数据能使应用程序正常工作;
当输入数据时,Web应用会验证输入的数据是否是正确;如果验证通过,应用允许提交这些数据到服务器端并储存到数据库中,如果验证未通过,则应用会提示有错误的数据,并且一般都会明确的提示错误发生在哪里;

表单的数据校验的作用:
希望以正确的格式获取到正确的数据:如果用户的数据以不正确的格式存储,或者没有输入正确的信息或都没有输入信息,Web应用程序将无法正常运行;
保护用户的信息安全:强制用户输入安全的密码,有利于保护他们的账户信息;
保障网站的安全:恶意用户有很多通过滥用应用中缺乏保护的表单破坏应用的方法;

表单数据校验的方式:
表单校验可以通过许多不同的方式实现,主要是两端校验;

客户端校验:
发生在浏览器端,表单数据被提交到服务器之前,这种方式相较于服务器端校验来说,用户体验更好,它能实时的反馈用户的输入校验结果,这种类型的校验可以进一步细分以下方式:
JavaScript校验:利用Javascript,可以完全自定义校验表单数据的实现方式;
HTML5约束校验:也就是HTML5内置的校验,其不需要JavaScript,而且性能更好,但是不如JavaScript校验那样可以自定义,灵活性不够;

服务器端校验:
发生在浏览器提交数据并被服务器端接收之后;通常服务器端校验都是发生在将数据写入数据库之前,如果数据没通过校验,则会直接从服务器端返回错误消息,并且告诉浏览器端发生错误的具体位置和原因;
服务器端校验的缺点是,不像客户端校验那样有比较好的用户体验,因为它直到整个表单都提交后才能返回错误信息;
服务器端校验是Web应用对抗错误或恶意数据的最后防线,在这之后,数据将被持久化至数据库;如今所有的服务端框架都提供了数据校验与安全功能;
在真实的项目开发过程中,几乎同时使用客户端校验与服务器端校验的组合校验方式,以确保数据的正确性与安全性,即两端校验

HTML5约束验证API:

也称为内置表单验证;为了在表单提交到服务器之前验证数据,HTML5为控件新增了一些约束验证的功能,有了这些功能,即使Javascript被禁用或由于种种原因未能加载,也可以确保基本的验证,但低版本的浏览器不支持或部分支持;

在表单提交时,如果表单元素未通过约束验证,浏览器将在第一个无效表单元素上显示错误消息,并且可以根据错误类型显示默认消息或自定义设置的消息;

约束属性:
required属性:必填,任何标有required属性的表单元素,在提交表单时都不能为空,其适用于<input>、<textarea>和<select>等元素;如:

<input type="text" name="username" required />
在Javascript中,使用对应的required属性,如:
// 检测浏览器是否支持required属性
var isRequiredSupported="required" in document.createElement("input");
// 检测required属性
var isUsernameRequired=document.forms[0].elements["username"].required;

如果输入一个空格,可以通过约束,像这种情况我们是不希望看到的,也是必须要避免的,所以此时还是需要Javascript来进行验证,如:

document.forms[0].addEventListener("submit", function(event){
    var textbox=document.forms[0].elements[0];
    if(textbox.value.trim()==""){
        console.log("不能为空");
        event.preventDefault();
    }
});

限制输入的长度:
所有文本框都可以使用minlength和maxlength属性来限制长度;如果输入的字段长度小于minlength的值或大于maxlength值则无效;Javascript可以使用minLength和maxLength属性来访问;如:

<input type="text" id="username" name="username" required minlength="4" maxlength="6" />
<script>
var username=document.forms[0].elements["username"];
console.log(username.minLength, username.maxLength);
</script>

type属性:增加了几种类型,这些新类型不仅能反映数据类型的信息,而且还能提供一些默认的验证功能;其中,”email”和”url”是得到支持最多的类型,如:

<input type="email" name="email" />
<input type="url" name="homepage" />

要检测浏览器是否支持这些新类型,可以在Javascript创建一个<input>元素,然后将type属性设置为”email”或”url”,最后再检测这个属性值,对于不支持它们的浏览器会自动将未知的值设置为“text”,而支持的浏览器则会返回正确的值,如:

var input=document.createElement("input");
input.type="email";
var isEmailSupported=(input.type=="email");

存在一个问题,“-@-”会被当成一个有效的邮件地址,这显然有点不合理;

document.forms[0].addEventListener("submit", function(event){
    var email=document.forms[0].elements["email"];
    if(email.value !=""){
        // 中文正则
        // ^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$
        var pattern=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
        if(!pattern.test(email.value)){
            console.log("请正确输入邮箱");
            event.preventDefault();
        }
    }
});

如果不为新类型的<input>设置required属性,那么空文本框也会验证通过;另外,设置特定的输入类型并不能阻止用户输入无效的值,只是应用某些默认的验证而已;

type为”tel”的元素:
"tel" 类型的元素用于让用户输入和编辑电话号码,但浏览器不会自动验证它的格式,因为世界各地的电话号码格式差别很大,所以其在功能、表现上与“text”一致;

<input id="tel" name="tel" type="tel" required />

即使如此,但其在移动端,可能会提供为输入电话号码而优化的自定义键盘;另外,使用电话号码的特定输入类型也使添加自定义验证和处理电话号码更方便;例如,要求电话必填,用到了required属性,并且格式是中国的手机号码格式,如:

document.forms[0].addEventListener("submit", function(event){
    var tel=document.forms[0].elements["tel"];
    // 固话 :(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}
    var telPattern=/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}$/;
    if(!telPattern.test(tel.value)){
        console.log("电话号码不正确");
        event.preventDefault();
    }
});

处理国际电话号码的方案,如:

<form>
<p>
    <label for="country">选择国家:</label>
    <select id="country" name="country">
        <option value="CN" selected>中国</option>
        <option value="UK">英国</option>
        <option value="US">美国</option>
        <option value="GER">德国</option>
    </select>
</p>
<p>
    <label>输入电话号码: </label>
    <input id="areaNo" name="areaNo" type="tel" required
                placeholder="区号" pattern="[0-9]{3,4}" />
    <input id="number1" name="number1" type="tel" required
                placeholder="号码" pattern="[0-9]{7,8}" />
    <input id="number2" name="number2" type="tel"
                placeholder="分机" pattern="[0-9]*" />
</p>
<p><button>提交</button></p>
</form>
<script>
var selectElem=document.querySelector("select");
var inputElems=document.querySelectorAll("input");
selectElem.onchange=function() {
  for(var i=0; i < inputElems.length; i++) {
    inputElems[i].value="";
  }
  if(selectElem.value==="CN"){
    inputElems[2].parentNode.style.display="inline";
    inputElems[0].placeholder="区号";
    inputElems[0].pattern="[0-9]{4}";
    inputElems[1].placeholder="号码";
    inputElems[1].pattern="[0-9]{7,8}";
    inputElems[2].required=false;
    inputElems[2].placeholder="分机";
    inputElems[2].pattern="[0-9]*";
  }else if(selectElem.value==="US") {
    inputElems[2].parentNode.style.display="inline";
    inputElems[0].placeholder="Area code";
    inputElems[0].pattern="[0-9]{3}";
    inputElems[1].placeholder="First part";
    inputElems[1].pattern="[0-9]{3}";
    inputElems[2].required=true;
    inputElems[2].placeholder="Second part";
    inputElems[2].pattern="[0-9]{4}";
  } else if(selectElem.value==="UK") {
    inputElems[2].parentNode.style.display="none";
    inputElems[0].placeholder="Area code";
    inputElems[0].pattern="[0-9]{3,6}";
    inputElems[1].placeholder="Local number";
    inputElems[1].pattern="[0-9]{4,8}";
  } else if(selectElem.value==="Ger") {
    inputElems[2].parentNode.style.display="inline";
    inputElems[2].required=true;
    inputElems[0].placeholder="Area code";
    inputElems[0].pattern="[0-9]{3,5}";
    inputElems[1].placeholder="First part";
    inputElems[1].pattern="[0-9]{2,4}";
    inputElems[2].placeholder="Second part";
    inputElems[2].pattern="[0-9]{4}";
  }
}
</script>

type为“search”的元素,与“text”功能和表现基本一致,只不过其右则有个删除号(X),所以在实际应用中,可以把它当作“text”一样使用;

type为”color”的元素,除了IE,其他浏览器都支持,其调用的是系统的调色板,并且并没有提供类型的约束验证;

<input type="color" id="color" name="color" value="#FF0000" />

需要注意的是,其value值必须加“#”号的16进制,且完整,如“#ff0000”,也不能使用关键字,如“red”,并且不能调节Alpha通道;

var color=document.forms[0].elements["color"];
color.addEventListener("change", function(event){
    document.body.style.backgroundColor=event.target.value;
});

各浏览器呈现的样式有可能不一致,可以统一采用按钮代替,如:

<input type="color" id="color" name="color" style="display: none;" />
<input type="button" id="btnColor" name="btnColor" value="调色板" />
<input type="text" id="txtColor" name="txtColor" placeholder="#FFFFFF" />
<script>
var btnColor=document.getElementById("btnColor");
btnColor.addEventListener("click", function(event){
    var color=document.getElementById("color");
    color.click();
    color.addEventListener("change", function(event){
        document.getElementById("txtColor").value=this.value;
    });
},false);
</script>

数值范围:
HTML5还定义了其他几个输入元素,这些元素都要求填写某种基于数字的值,如:”number”、”range”、”datetime”、”datetime-local”、”date”、”month”、”week”和”time”;浏览器对这些类型的支持并不友好;
对于所有这些数值类型的输入元素,可以指定min、max和step属性(步长值或差值),如:

<input type="number" min="20" max="100" step="5" name="age" />

检测浏览器是否支持,方法同上;

在Javascript中,以上属性都有相对应的同名属性,另外,还存在两个方法:stepUp()和stepDown(),都接收一个可选的参数:在当前值的基础上加上或减去的step倍数的数值(默认加减1),如:

var age=document.forms[0].elements["age"];
age.stepUp(); // 增加5,因为step为5
age.stepUp(10); // 增加50,为step的10倍
age.stepDown(); // 减少5
age.stepDown(3); // 减少step的3倍,15

IE在输入非数字的情况下也可以通过约束,因此,需要使用Javascript判断验证,如:

var age=document.forms[0].elements["age"];
age.addEventListener("keypress", function(event){
    var charCode=event.charCode;
    if(!/\d/.test(String.fromCharCode(charCode)))
        event.preventDefault();
});

type为range的元素,IE9不支持,并且在各浏览器中呈现的样式并不一致;

<input type="range" max="50" min="10" step="2" value="30" />

其拥有属性:

  • max:设置或返回滑块控件的最大值;
  • min:设置或返回滑块控件的最小值;
  • step:设置或返回每次拖动滑块控件时的递增量;
  • value:设置或返回滑块控件的 value 属性值;
  • defaultValue:设置或返回滑块控件的默认值;
var range=document.querySelector('input[type="range"]');
console.log(range.max);
console.log(range.min);
console.log(range.step);
console.log(range.value);
console.log(range.defaultValue);

type为”date”、”datetime”、”datetime-local”、”month”、”week”和”time”,IE不支持,所有浏览器不支持”datetime”,Firefox只支持”date”和”time”;各浏览器呈现的也不一致;所以目前在所有应用中,并不会使用这些表单元素;对于不支持的表单元素,浏览器直接解析为type为“text”元素;

pattern属性:输入模式
该属性也是HTML5新增的,其值是一个正则表达式,用于匹配文本框中的值;、

<input type="text" name="age" pattern="\d+" />
<!-- 限制为4-8个字符,并要求它只包含小写字母 -->
<input type="text" id="username" name="username" pattern="[a-z]{4,8}" required />
<!-- 包含大小写字母和数字的组合,长度在8-10之间 -->
<input type="password" id="pwd" name="pwd" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}" />

注,模式的开头和末尾不用加^和$;

在Javascript中,通过同名的pattern属性来访问模式,如:

var pattern=document.forms[0].elements[0].pattern;
// 检测是否支持
var isPatternSupported="pattern" in document.createElement("input");
// 身份证号
var id=document.getElementById("id");
id.pattern="([0-9]){17}(\\d|x|X)";

注:<textarea>不支持pattern属性;

有一些<input>元素类型不需要pattern属性进行校验,例如”email”和”url”类型,因为它们本身就具有类型格式的校验;即使如此,也可以同时使用pattern属性,可以更加详细和灵活的定制约束规则;

检测有效性:
使用表单元素的checkValidity()方法可以检测该元素的值是否有效,如果其值有效,该方法返回true,否则返回false;
其判断是否有效的依据就是以上所讲的约束;如:

<input type="text" id="username" name="username" pattern="[a-z]{4,8}" required />
<p><input type="button" id="btn" name="btn" value="按钮" /></p>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    var username=document.getElementById("username");
    console.log(username.checkValidity());
    if(username.checkValidity()){
        console.log("约束通过");
    }else{
        console.log("不通过");
    }
},false);
</script>

要检测整个表单是否有效,可以在表单自身上调用checkValidity()方法;如果所有表单控件都有效,该方法返回true,即使其中一个表单无效,该方法都会返回false,如:

btn.addEventListener("click", function(event){
    if(document.forms[0].checkValidity()){
        console.log("约束通过");
    }else{
        console.log("不通过");
    }
},false);

validity属性:
checkValidity()方法只会返回是否有效的结果,但表单元素的validity属性则会返回有效或无效的原因,该属性是一个ValidityState类型的对象:

btn.onclick=function(){
    var num=document.forms[0].elements["num"];
    console.log(num.validity);  // ValidityState
}

其包含一系列属性,每个属性会返回一个布尔值:

  • patternMismatch:如果值与指定的pattern属性不匹配,返回true;
  • rangeOverflow:如果值比max值大,返回true;
  • rangeUnderflow:如果值比min值小,返回true;
  • stepMisMatch:如果step步长值不合理,返回true,step=“any”永远不会抛出此错误;
  • tooLong:如果值的长度超过了maxlength属性指定的长度,返回true;有的浏览器会自动约束字符数量,因此这个值可能永远都返回false;
  • tooShort:如果值的长度低于minlength属性指定的长度,返回true;
  • typeMismatch:如果值不是”email”或”url”等要求的格式,返回true;
  • valueMissing:如果标注为required的元素中没有值,返回true;
  • badInput:如果浏览器无法转换用户的输入,返回true;例如,number类型的输入元素,但其内容是字符串;
  • customError:如果设置了setCustomValidity(),则为true,否则为false;
  • valid:如果这里的其他属性都是false;checkValidity()方法也要求相同的值;

对于这些布尔属性中的每一个,值为true就表示验证失败;如果出现失败,浏览器将提醒用户并阻止提交表单;如果验证成功,即其他属性均返回false,则valid将为true,就可以提交表单;
因此,要想得到更具体的信息,就应该使用validity属性来检测表单元素的有效性,如:

<p><input type="email" name="email" id="email" required pattern="[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+" maxlength="10" /></p>
<p><input type="button" id="btn" name="btn" value="按钮" /></p>
</form>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    var email=document.getElementById("email");
    if(email.validity && !email.validity.valid){
        if(email.validity.valueMissing)
            console.log("请输入数据");
        else if(email.validity.typeMismatch)
            console.log("请输入邮件地址");
        else if(email.validity.tooLong)
            console.log("超出长度");
        else if(email.validity.patternMismatch)
            console.log("地址中不能包括特殊字符");
        else
            console.log("啥玩意啊");
    }
},false);
</script>

自定义错误信息:
主要使用validationMessage属性和setCustomValidity()方法;如果没有通过验证,浏览器会有默认地提示信息,该信息保存在表单元素的validationMessage属性中,如:

var email=document.forms[0].elements["email"];
console.log(email.validationMessage); // 如果有required特性,提示"请填写此字段"
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    var email=document.getElementById("email");
    // 根据不同的验证失败的原因,提示各自默认的信息
    if(email.validity && !email.validity.valid){
        if(email.validity.valueMissing)
            console.log(email.validationMessage);  // 请填写此字段
        else if(email.validity.typeMismatch)
            // 请在电子邮件地址中包括“@”。“a”中缺少“@”。
            console.log(email.validationMessage); 
        else if(email.validity.tooLong)
            console.log(email.validationMessage);
        else if(email.validity.patternMismatch)
            // 请与所请求的格式保持一致。
            console.log(email.validationMessage);
        else
            console.log(email.validationMessage);
}
    // 或者
    // if(email.validity && !email.validity.valid){
    //     console.log(email.validationMessage);
    // }
},false);

但是该属性是只读的,如果想修改这个值,可以调用setCustomValidity()改变validationMessage的值;如:

var email=document.forms[0].elements["email"];
email.setCustomValidity("不要懒,必须填!");
email.validationMessage='这个字段必须填上。';
console.log(email.validationMessage);

现在再单击提交,如果没有验证通过,会提示自定义的消息;
如果将自定义错误设置为truthy值,则将阻止提交表单;因为调用了setCustomValidity()方法,所以validity的customError属性为true,导致validy属性为false,所以提交不了;

var btnsubmit=document.querySelector('input[type="submit"]');
btnsubmit.addEventListener("click", function(event){
    console.log(email.validationMessage);
    console.log(email.checkValidity());  // false
    // customError: true, valueMissing: true, valid: false
    console.log(email.validity); 
});

只有将自定义消息设置为空才能提交表单,而将自定义消息设置为空,也就是将消息恢复为浏览器默认的消息,如:

btnsubmit.addEventListener("click", function(event){
    if (email.value !="") {
        email.setCustomValidity("");
    }
    console.log(email.validationMessage);  // 默认的消息,地址包含@
    console.log(email.checkValidity());  // false
    // typeMismatch:true, valid: false
    console.log(email.validity); 
});

如果此时没有下一个约束,或者其他验证均有效的话,就可以顺利得交了;

当然,这些代码放到一个普通按钮的click事件处理程序中也是可以的,如:

var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    if (email.value !="") {
        email.setCustomValidity("");
    }
    console.log(email.validationMessage);
    console.log(email.checkValidity());
    console.log(email.validity); 
    if (!email.checkValidity()) {
        console.log(email.validationMessage);
    }else{
        document.forms[0].submit();
    }
});

可以根据不同的约束验证失败时分别自定义提示消息,如:

function validate(input) {
    var validityState=input.validity;
    if(validityState.valueMissing){
        input.setCustomValidity('必填');
    }else if(validityState.typeMismatch){
        input.setCustomValidity('类型不正确');
    }else if(validityState.rangeUnderflow) {
        input.setCustomValidity('值太小');
    }else if(validityState.rangeOverflow) {
        input.setCustomValidity('值太大');
    }else if(validityState.stepMisMatch){
        input.setCustomValidity('步长值不合理');
    }else if(validityState.tooLong){
        input.setCustomValidity('长度超出了maxLength');
    }else if(validityState.tooShort){
        input.setCustomValidity('长度小于minLength');
    }else if(validityState.patternMismatch){
        input.setCustomValidity("格式不正确");
    }else if(validityState.badInput){
        input.setCustomValidity('值类型无法转换');
    } else {
        input.setCustomValidity('');
    }
    return validityState.valid;
}
// 应用
var btnsubmit=document.querySelector('input[type="submit"]');
btnsubmit.addEventListener("click", function(event){
    var email=document.getElementById("email");
    if(!validate(email)){
        console.log(email.validationMessage);
        console.log(email.checkValidity());
        console.log(email.validity); 
    }
});
// 或者普通按钮
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    var email=document.getElementById("email");
    if(!validate(email)){
        console.log(email.validationMessage);
        console.log(email.checkValidity());
        console.log(email.validity); 
    }else{
        document.forms[0].submit();
    }
});

也可以配合正则表达式,设备自定义错误消息,如:

<form>
    <label for="ZIP">邮编:</label>
    <input type="text" id="ZIP">
    <label for="Country">国家:</label>
    <select id="Country">
        <option value="cn">中国</option>
        <option value="ch">瑞士</option>
        <option value="fr">法国</option>
        <option value="de">德国</option>
        <option value="nl">荷兰</option>
    </select>
    <input type="submit" value="Validate">
</form>
<script>
function checkZIP() {
    // 定义每个国家对应的,邮政编码必须遵循的模式及消息
    var constraints={
        cn : [ '^(CN-)?\\d{5}$', "中国邮编需要5个数字:例如CN-10022或10022"],
        ch : [ '^(CH-)?\\d{4}$', "瑞士邮编需要4个数字:例如CH-1950或1950" ],
        fr : [ '^(F-)?\\d{5}$' , "法国邮编需要5个数字:例如F-75012或75012" ],
        de : [ '^(D-)?\\d{5}$' , "德国邮编需要5个数字:例如D-12345或12345" ],
        nl : [ '^(NL-)?\\d{4}\\s*([A-RT-Z][A-Z]|S[BCE-RT-Z])$',
                        "荷兰邮编需要4位数字,后跟除SA、SD和SS之外的2个字母" ]
    };
    var country=document.getElementById("Country").value;
    var ZIPField=document.getElementById("ZIP");
    // 创建正则对象
    var constraint=new RegExp(constraints[country][0], "");
    console.log(constraint);
    // 检测
    if(constraint.test(ZIPField.value)) {
        // 通过约束校验
        ZIPField.setCustomValidity("");
    }else{
        // 没有通过约束校验,设置当前国家的错误消息
        ZIPField.setCustomValidity(constraints[country][1]);
    }
}
window.onload=function () {
    document.getElementById("Country").onchange=checkZIP;
    document.getElementById("ZIP").oninput=checkZIP;
}
</script>

novalidate属性和formnovalidate属性:
禁用验证,可以设置表单不进行验证;

<form name="myform" novalidate ></form>

在Javascript中使用noValidate属性可以获取或设置这个值,如果这个属性存在,值为true,否则为false;

document.forms[0].noValidate=true;  // 禁用验证

如果一个表单中有多个提交按钮,为了指定点击某个提交按钮不必验证表单,可以在相应的按钮上添加formnovalidate属性,如:

<form name="myform">
    <input type="submit" value="验证提交" />
    <input type="submit" formnovalidate value="不验证提交" />
</form>

使用Javascript也可以设置这个属性:

document.forms[0].elements["btnNoValidate"].formNoValidate=true;

一般情况下,表单使用novalidate属性关闭浏览器的自动校验的目的,就是使用脚本控制表单的校验;但是,这并不会禁止对约束校验的支持或对约束CSS伪类的支持;如:

<style>
input:invalid{border-color: #900; background-color: #FDD;}
input:focus:invalid{outline: none;}
.error {color: white; background-color: lightgreen; padding: 0.1em 0.2em;}
.error.active {background-color: red;}
</style>
<form novalidate>
    <p>邮箱地址:<input type="email" id="mail" name="mail" required />
        <span class="error">如:a@a.com</span></p>
    <button>提交</button>
</form>
<script>
var form=document.getElementsByTagName('form')[0];
var email=document.getElementById('mail');
var error=document.querySelector('.error');
email.addEventListener("input", function (event) {
  if (email.validity.valid) {
    error.innerHTML="正确"; 
    error.className="error"; 
  }
}, false);
form.addEventListener("submit", function (event) {
  if(!email.validity.valid){
    error.innerHTML="期望一个正确邮箱地址";
    error.className="error active";
    event.preventDefault();
  }
}, false);
</script>

invalid事件:
当表单提交时,若任一个表单元素在检查有效性时,不符合对它的约束条件,则会触发invalid事件;对元素有效性的检查是在提交表单之前或调用表单或表单元素自己的checkValidity()方法之后;

<form>
    输入1-10之间的整数:<input type="number" min="1" max="10" required /><br/>
    <input type="submit" value="提交" />
    <input type="button" id="btn" name="btn" value="按钮" />
</form>
<p id="log">错误:</p>
<script>
var input=document.querySelector('input[type="number"]');
var log=document.getElementById("log");
// 当提交表单时触发
input.addEventListener("invalid", function(event){
    log.textContent +=event.target.validationMessage;
});
// 调用checkValidity()也会触发
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    console.log(input.validity);
    input.checkValidity();  // 触发invalid事件
});
</script>

在也可以invalid事件中自定义错误消息,如:

<form>
    输入大小写字母:<input type="text" name="username" id="username" required pattern="[A-Za-z]+">
    <input type="submit" value="提交" />
    <input type="button" id="btn" name="btn" value="按钮" />
</form>
<script>
var username=document.querySelector('#username');
username.addEventListener('input', function(e){
    // 如果一开始没有验证通过,必须在此设为空字符串,否则即使有效也无法提交
    username.setCustomValidity('');
    username.checkValidity();
});
// 提交时触发
username.addEventListener('invalid', function(e){
//   if(username.value==='') {
//     username.setCustomValidity('请输入用户名');
//   } else {
//     username.setCustomValidity('用户名只能包含大写和小写字母');
//   }
	// 或者
    if(username.validity.valueMissing) {
        username.setCustomValidity('请输入用户名');
    }else if(username.validity.patternMismatch){
        username.setCustomValidity('用户名只能包含大写和小写字母');
    }
});
// 调用checkValidity()触发
var btn=document.getElementById("btn");
btn.addEventListener("click", function(event){
    console.log(username.validity);
    if(!username.checkValidity()){  // 触发invalid事件
        console.log(username.validationMessage);
    }else{
        document.forms[0].submit();
    }
});
</script>

:valid和:invalid伪类:
:valid CSS伪类表示表单或表单元素数据验证通过的样式;
:invalid CSS伪类表示表单或表单元素未通过验证样式;
这两个伪类能简单地将校验字段展示为一种能让用户辨别出其输入数据的正确与否的样式;

<style>
form:invalid {
  border: 5px solid #ffdddd;
}
form:valid {
  border: 5px solid #ddffdd;
}
input:valid {
  background-color: powderblue;
}
input:invalid{
    background-color: pink;
}
</style>

如:验证电话号码:

<style>
div {margin-bottom: 10px; position: relative;}
input[type="tel"] {width: 100px;}
input + span {padding-right: 30px;}
input:invalid+span:after {
  position: absolute; content: '?';
  padding-left: 5px; color: #8b0000;
}
input:valid+span:after {
  position: absolute;
  content: '?'; padding-left: 5px; color: #009000;
}
</style>
<div>
    <label for="tel">电话号码(必填): </label>
    <input id="tel" name="tel" type="tel" required>
    <span class="validity"></span>
</div>

:required伪类和:optional伪类:
:required CSS伪类表示任意设置了required属性的<input>、<select>或<textarea>元素;这个伪类对于高亮显示在提交表单之前必须具有有效数据的字段非常有用;
:optional CSS伪类表示任意没有required属性的<input>、<select>或<textarea>元素使用它;

input:required{
    border: 1px solid green;
}
input:optional {
  border: 1px dashed black;
}

:in-range伪类和:out-of-range伪类:使用方式同上;

不使用内置表单校验API:
对于老旧浏览器并不支持HTML的约束校验,因此只能使用JavaScript来校验表单数据,如:

<style>
input.invalid{border-color: #900; background-color: #FDD;}
input:focus.invalid{outline: none;}
.error {color: white; background-color: lightgreen; padding: 0.1em 0.2em;}
.error.active {background-color: red;}
</style>
<form>
    <p>邮箱地址:<input type="text" class="mail" id="mail" name="mail">
            <span class="error">如:a@a.com</span><p>
    <button type="submit">提交</button>
</form>
<script>
var form=document.getElementsByTagName('form')[0];
var email=document.getElementById('mail');
var error=email;
while ((error=error.nextSibling).nodeType !=1);
var emailRegExp=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
function addEvent(element, event, callback) {
    element["on" + event]=function (e) {
        var output=callback(e);
        if (output===false)
            return false;
    };
};
addEvent(window, "load", function () {
    var test=email.value.length===0 || emailRegExp.test(email.value);
    email.className=test ? "valid" : "invalid";
});
addEvent(email, "input", function () {
    var test=email.value.length===0 || emailRegExp.test(email.value);
    if(test){
        email.className="valid";
        error.innerHTML="正确";
        error.className="error";
    } else {
        email.className="invalid";
    }
});
addEvent(form, "submit", function () {
    var test=email.value.length !==0 || emailRegExp.test(email.value);
    console.log(test);
    if(!test){
        email.className="invalid";
        error.innerHTML="需要一个正确的邮箱地址";
        error.className="error active";
        return false;
    }else{
        email.className="valid";
        error.innerHTML="正确";
        error.className="error";
    }
});
</script>

远程校验:
当用户输入的数据与存储在应用程序服务器端的附加数据绑定时,这种校验是必要的,一般采用Ajax异步请求进行校验;

篇介绍了表单的使用,表单有很多控件,比如输入框,密码框、文本域,按钮等。按类型可分如下:

  • 输入类控件
  • 菜单类控件

输入类组件 —— input

此类控件有很多种类型,使用<input type="类型">语法,常见类型如下:

type 值

含义

text

文字字段

password

密码域,用户看不到明文,以*代替

radio

单选按钮

checkbox

多选按钮

button

普通按钮

submit

提交按钮

reset

重置按钮

image

图像域,用图像作为背景的提交按钮

hidden

隐藏域,不可见的输入框

file

文本域,用于上传文件等非文本数据

文本输入框和密码框

除了显示形式不一样,其它属性一样,有以下属性:

  • name —— 定义文字字段名称,用于和其它控件区别,不能包含特殊字符,也不可使用html 标签名称
  • maxlength —— 定义文本框可输入字符最大长度
  • size —— 定义文本框在页面中显示的长度
  • vaule —— 定义文本框中默认的值

如下是文本输入框和密码框制作一个登录表单

html代码:

<!DOCTYPE html>
<html>
<body>
<h1>用户登录</h1>
<form action="/demo/html/action_page.php">
  <label for="fname">用户名:</label><br>
  <input type="text" id="username" name="username" value=""><br>
  <label for="lname">密码:</label><br>
  <input type="password" id="pwsd" name="pwsd" value=""><br><br>
  <input type="submit" value="提交">
</form> 
</body>
</html>

显示效果:

HTML5 输入类型

除了以上几种类型,HTML5 还增加了多个新的输入类型:

  • color
  • date
  • datetime
  • datetime-local
  • email
  • month
  • number
  • range
  • search
  • tel
  • time
  • url
  • week

如下代码:

<!DOCTYPE html>
<html>
<body>
<form action="/demo/demo_form.asp">
  数字类型(1 到 5 之间):
  <input type="number" name="quantity" min="1" max="5">
  IE9 及早期版本不支持 type="number"。<br>
  color 选择颜色:
  <input type="color" name="color"><br>
   生日:
  <input type="date" name="bday"><br>
  年月:
  <input type="month" name="bdaymonth"><br>
  年周:
  <input type="week" name="week_year"><br>
  时间:
  <input type="time" name="usr_time"><br>
  一定范围
   <input type="range" name="points" min="0" max="10"><br>
   E-mail:
  <input type="email" name="email">
  能够在被提交时自动对电子邮件地址进行验证<br>
  搜索:
  <input type="search" name="googlesearch"><br>
  电话:
  <input type="tel" name="usrtel">
  目前只有 Safari 8 支持 tel 类型。<br>
  url:
  <input type="url" name="url">
  提交时能够自动验证 url 字段<br>
  <input type="submit">
</form>
</body>
</html>

效果如下:

单选和多选按钮

使用 type=“radio” 和 type=“checkbox” 定义是单选还是多选,除了name和value属性外,单选和多选都有一个 checked属性定义默认选择的项,checked=“true”指选中那个选项,表单会将 checked=“true” 的选型值传递给后台。

如下实例:

<!DOCTYPE html>
<html>
<body>
<h4>单选和多选</h4>
<form action="/demo/demo_form.asp">
水果:
<input type="radio" name="shuiguo" value="banner" checked> 香蕉
<input type="radio" name="shuiguo" value="apple"> 苹果
<br><br>
省份:
<input type="checkbox" name="shengfen" value="shannxi" checked> 陕西
<input type="checkbox" name="shengfen" value="sanxi"> 山西
<input type="checkbox" name="shengfen" value="gdong"> 广东
<br><br>
<input type="submit">
</form> 
</body>
</html>

显示效果:

单选和多选传递给后台的数据是不一样的,如下会看到地址栏中的数据,多选会发送多个值,后台将会获取一个数组形式的数据。

/demo/demo_form.asp?shuiguo=banner&shengfen=shannxi&shengfen=sanxi

普通按钮、提交按钮、重置按钮

普通按钮:type=“button”,一般配合脚本使用,语法如下:

<input type="button" name="名称" value="按钮值" onclick="脚本程序" />

value 值就是按钮在页面显示的文字,onclick属性定义了脚本事件,这里指单击按钮时所进行的处理。

如下示例:

<!DOCTYPE html>
<html>
<body>
<form>
 <input type="button" value="普通按钮">
<input type="button" value="打开窗口" onclick="window.open()">
<input type="button" value="您好" onclick="alert('您好')">
  </form>
</body>
</html>

单击您好按钮

提交按钮:type=“submit”,用于提交表单内容,是一种特殊按钮。

如刚才的登录表单,提交后会返回结果:

重置按钮:type="reset",用于清除表单数据,也是一种特殊按钮。

输入数据

点击重置按钮后,表单数据清空

重置清空数据

HTML5 按钮

除了使用input定义按钮,还可以使用 html5 新增的<button> 标签定义按钮,button 使用语法如下:

<form action="/demo/html/action_page.php">
<button type="button">普通按钮</button>
<button type="submit">提交按钮</button>
</form> 

其它输入类控件

隐藏域 —— hidden
文件域 —— file

如下示例:

<form action="/demo/html/action_page.php">
  <label for="fname">隐藏域:</label>
  <input type="hidden" id="hidden" name="hidden" value=""><br>
  <label for="lname">文件域:</label>
  <input type="file" id="file" name="file" value=""><br>
  <input type="submit" value="提交">
</form> 

显示效果

可以看到,隐藏域在页面中不显示,单击文件域选择文件按钮可以选择文件,比如word文件,电子表格文件等,会以非文本方式传送到后台的,常用来实现文件上传功能。

文本域 —— textarea

除了input 类型的控件,还有文本域 textarea ,一种特殊的文本框,它与input 文本输入框的区别就是可以输入多行文字,input 文本输入框是单行的无法输入多行文字。

如下示例:

<p>textarea 元素定义多行输入字段。</p>
<form action="/demo/html/action_page.php">
  <textarea name="message" rows="10" cols="30">The cat was playing in the garden.</textarea>
  <br><br>
  <input type="submit">
</form>

效果如下:

rows 属性定义文本域的高度是几行,cols 定义文本域宽度占几列,比如上面定义了高10行宽30列的文本域。

下拉菜单和多选列表

下拉菜单作用和单选按钮类似,只不过它更加节省空间,当要选择的选型很多时,就不适合使用radio空间,所以当选项很多的时候,使用下拉菜单,语法如下:

<select name="名称">
<option value="选项值1" selected>选项1</option>
<option value="选项值2">选项3</option>
更多option......
</select>

多选列表和多选按钮类似,一样为了节省空间,当数据选项比较多时,使用多选列表,语法如下:

<select name="名称" size="可看见的列表项数" multiple>
<option value="选项值1" selected>选项1</option>
<option value="选项值2">选项3</option>
更多option......
</select>

多选比下拉菜单不同之处是多了一个multiple属性,定义多选的,且表现形式也不一样,不是下拉而是一个列表。

如下代码:

<!DOCTYPE html>
<html>
<body>
<form action="/demo/demo_form.asp">
下拉菜单:<br>
<select name="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="fiat">Fiat</option>
<option value="audi">Audi</option>
</select>
<br>
多选列表:<br>
<select name="cars" size="3" multiple>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="fiat">Fiat</option>
<option value="audi">Audi</option>
</select>
<br><br>
<input type="submit">
</form>
</body>
</html>

显示效果:

这里需要注意的是,多选列表多选时需要按住ctrl键同时鼠标单击选择才能多选,效果如下:

到这里,已介绍了大部分的表单控件,现在你可以使用他们制作自己的表单,表单通常在动态网站中使用,这为以后制作动态网站打下基础。

还有许多属性没有讲到,比如html5新增的一些属性和功能,可自行参考 w3cshool 等网站学习,感谢关注,学习愉快!

上篇 : 前端入门——html 表单

下篇: 前端入门 —— 网页中使用窗口框架