checkValidity等form原生JS验证方法和属性详细介绍

这篇文章发布于 2019年08月18日,星期日,23:03,归类于 JS API。 阅读 35845 次, 今日 3 次 9 条评论

 

一、先从form内置验证的外部表现说起

说起form内置验证,很多人想到的是设置required这样的HTML属性,然后表单提交的时候出现这样的提示效果:

form内置提示效果

实际上,这只是表象,只是form表单原生验证的一小部分。form内置验证的精髓其实不止这点表面的东西。

例如CSS侧有诸多匹配的伪类,如:required伪类, :optional伪类或是:valid:invalid伪类等。

又例如JS DOM事件这块表单元素可以监听'invalid''valid'事件。

又例如JS DOM API这一块则有诸多内置的验证方法和属性,这就是本文要介绍的知识点。

二、form表单元素内置验证方法和属性

开门见山不打弯,共3个方法和1个属性。

3个方法分别是checkValidity(), reportValidity(), setCustomValidity()方法,1个属性是validity属性。

具体如下:

checkValidity()方法

checkValidity()方法可以用来验证当前表单控件元素,或者整个表单是否验证通过,返回值是布尔值,true或者false

例如,某下拉框元素是否验证通过:

var isSelectPassing = document.querySelector('select').checkValidity();    // true或false

下拉框元素的验证

或者整个表单元素是否验证通过:

var isFormPassing = document.forms[0].checkValidity();    // true或false

form元素调用验证方法

reportValidity()方法

reportValidity()方法可以触发浏览器的内置的验证提示交互,返回布尔值,true或者false。例如:

document.querySelector('select').reportValidity()

会触发下拉框的错误提示,如下图所示:

下拉框验证提示触发

另外,reportValidity()方法IE浏览器并不支持,Edge 17+开始支持。

setCustomValidity()方法

顾名思义就是设置自定义的验证,我们可以使用这个方法自定义提示文字。

语法如下:

ele.setCustomValidity(str);

其中,str为字符串,表示出错提示的文字信息,如果是空字符串,则表示不使用自定义的错误提示。

例如上面的reportValidity()方法的下拉出错提示是“请在列表中选择一项”。

如果我们希望改成“请选择城市”,则可以下面这样:

var eleSelect = document.querySelector('select');
if (eleSelect.validity.valueMissing == true) {
    eleSelect.setCustomValidity('请选择城市');
}
eleSelect.reportValidity();

此时,提示效果就是:

改变提示的文案信息

validity属性与ValidityState对象

每一个标准的表单控件,例如输入框,下拉框以及单复选框都内置一个validity属性,这是个只读属性,可以返回当前元素各种验证状态,例如:

console.dir(document.querySelector('select').validity);

在Chrome浏览器下返回的结果是一个ValidityState对象,包含的属性和属性值如下:

badInput: false
customError: false
patternMismatch: false
rangeOverflow: false
rangeUnderflow: false
stepMismatch: false
tooLong: false
tooShort: false
typeMismatch: false
valid: false
valueMissing: true

控制台输出截图如下:

内置的验证状态对象

其中

badInput
只读。属性值为布尔类型。输入框里面的值浏览器没办法进行转换。例如'number'类型输入框里面是中文字符(MDN上说法,但是自己测试无法复现),此时值是true。此属性IE浏览器并不支持。此属性建议了解即可。
customError
只读。属性值为布尔类型。如果元素调用setCustomValidity()方法设置了自定义的验证信息则值是true
patternMismatch
只读。属性值为布尔类型。和指定的pattern正则属性值不匹配的时候值是true。会匹配:invalid这个CSS伪类。
rangeOverflow
只读。属性值为布尔类型。超过max属性设置的值的时候会是true。同时会匹配CSS :invalid:out-of-range伪类。
rangeUnderflow
只读。属性值为布尔类型。小于min属性设置的值的时候会是true。同时会匹配CSS :invalid:out-of-range伪类。
stepMismatch
只读。属性值为布尔类型。输入框当前值和step属性值不匹配的时候stepMismatch的值会是true。同时元素会匹配CSS :invalid:out-of-range伪类。
tooLong
只读。属性值为布尔类型。输入内容长度超出maxlength的限制时候会是true。同时会匹配CSS :invalid:out-of-range伪类。
tooShort
只读。属性值为布尔类型。输入内容长度不足minlength的限制时候会是true。同时会匹配CSS :invalid:out-of-range伪类。此属性IE浏览器并不支持,因为不支持minlength属性。
typeMismatch
只读。属性值为布尔类型。输入框的值和输入框类型不匹配的时候该属性值会是true。例如输入框type类型是email或者url时候。如果值是true,会匹配:invalid这个CSS伪类。
valid
只读。属性值为布尔类型。当前元素是否完全验证通过,通过是true,会匹配:valid这个CSS伪类;不通过是false,会匹配:invalid这个CSS伪类。
valueMissing
只读。属性值为布尔类型。如果元素设置了required属性,同时输入框的值为空,则该属性值是true。如果值是true,会匹配:invalid这个CSS伪类。

补充于2021-07-30

validationMessage属性

语法如下:

var message = ele.validationMessage;

表示,当前输入框元素如果要显示出错提示,出错提示的文字内容是什么。

例如一个普通的输入框:

<input id="input">

input.validationMessage的返回值是空字符串''

如果输入框设置了required属性:

<input id="input" required>

input.validationMessage的返回值是:’请填写此字段。’

如果输入框设置了pattern属性,同时输入框里面的值格式不符:

<input id="input" required pattern="^\d{6}$">

input.validationMessage的返回值是:’请与所请求的格式保持一致。’

以及其他一些常见就不举例了,运行结果示意如下截图:

验证提示信息说明

willValidate属性

语法如下:

var result = ele.willValidate;

表示元素能够被验证。

输入框元素都是true,但是如果输入框是disabled禁用的,则resultfalse

这里这张测试结果示意图:

willValidate值是false

三、IE9浏览器的polyfill

以上所有原生的表单验证方法和属性IE9浏览器都不支持,IE10+浏览器都支持。

表单原生验证方法兼容性

如果想要IE9浏览器也支持,需要写个polyfill,我大概搜索了下,checkValidity()等几个方法并没有合适的polyfill,已有的一些项目为了兼容IE8,更像是shim,没有专门为IE9打造了polyfill。

倒是validity属性找到个看上去有些靠谱的polyfill。您可以狠狠地点击这里(可以右键→另存为):validity-polyfill.js。这个polyfill出自这里,不过我并没有仔细验证过其正确性。

之后我会自己针对IE9浏览器吧checkValidity()等几个方法给补上。

四、写着写着就成了文档

本文下笔之处还以为会发现一些好玩的东西,例如自定义表单验证逻辑,后来发现自己想多了,setCustomValidity()方法并没有自己预想的那么强大,就是个改变提示文字信息的方法。

整理来整理去,最后就成了一个比较详尽的关于表单原生验证的文档了。

之后写验证组件,我会借助这些原生的已经内置好的验证方法来实现,可以省去不少功夫,会很有意思。

日后的精彩演绎源自平时平淡的积累。

对于大部分的人,对于本文这些API是无感的,想不到如何在实际项目中应用,觉得很鸡肋,实际上大有可为的,我已经想要跃跃欲试了,嘿嘿。

(本篇完)

分享到:


发表评论(目前9 条评论)

  1. CommandNotFound ⚡️ 坑否说道:

    如果页面里100个表单元素,提交的时候,调用 form[0].checkValidity ,但是这个整体返回 true 或者 false,那如何知道是哪一个元素 required 的时候出了问题导致整体没通过呢

  2. saber说道:

    棒,这样不用 UI 库的表单验证方法了

  3. lbca说道:

    能静下心来把原生api研究的如此透彻,真的很厉害👍

  4. 刘东奇说道:

    见过这种样式的表单验证提示,当时以为是插件实现的样式,现在才知道原来是原生的。

  5. Sinosaurus说道:

    挺好的,我之前尝试用原生校验用在项目上,结果在firefox上,会有红色边框(Firefox特意添加的),结果被产品dist了。

  6. XboxYan说道:

    哈哈,上周做的基于checkValidity验证做的表单组件
    https://xy-ui.codelabo.cn/docs/#/xy-form?id=%e4%ba%a4%e4%ba%92%e5%ae%9e%e4%be%8b

  7. Ye Xu说道:

    除了 validity 之外,还有两个属性:
    1. validationMessage
    2. willValidate

  8. yugasun说道:

    前排, mark