表单概述
表单(<form>
)用来收集用户提交的数据,发送到服务器。
常见的表单是登陆界面,用户提交用户名和密码,让服务器验证。
<form action="/handling-page" method="post">
<div>
<label>用户名:
<input type="text" id="name" name="user_name" />
</label>
</div>
<div>
<label>密码:
<input type="password" id="passwd" name="user_passwd" />
</label>
</div>
<div>
<input type="submit" id="submit" name="submit_button" value="提交" />
</div>
</form>
上面代码就是一个简单的表单,包含三个控件:用户名输入框、密码输入框和提交按钮。
用户点击“提交”按钮,每一个控件都会生成一个键值对,键名是控件的name属性,键值是控件的value属性,键名和键值之间由等号连接。比如,用户名输入框的name属性是user_name,value属性是用户输入的值,假定是“张三”,提交到服务器的时候,就会生成一个键值对user_name=张三。
表单基础
在 JS 中表单的类型以 HTMLFormElement 表示。这个类型继承自 HTMLElement。
除了平常获取元素的方法比如 querySelector 、getElementById 外,还可以使用 document.forms 来获取到页面的所有表单元素。
<form name="myForm">
</form>
<form name="myForm2">
获得的是这样的表单结果
所以我们可以使用索引来获取对应的表单元素。
document.forms['myForm2'] //获取名字为myForm2的表单元素
docoment.form[0] //获得第一个表单
method
所有的键值对都会提交到服务器。但是,提交的数据格式跟<form>
元素的method属性有关。该属性指定了提交数据的 HTTP 方法。如果是 GET 方法,所有键值对会以 URL 的查询字符串形式,提交到服务器,比如/handling-page?user_name=张三&user_passwd=123&submit_button=提交。下面就是 GET 请求的 HTTP 头信息。
GET /handling-page?user_name=张三&user_passwd=123&submit_button=提交
Host: example.com
如果是post方法,那么数据就会作为请求体发送给服务器。所有键值对会连接成一行。下面就是 POST 请求的头信息。
POST /handling-page HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 74
user_name=张三&user_passwd=123&submit_button=提交
但是实际提交的时候,只要键值不是 URL 的合法字符,比如上面的汉字张三和提交,那么浏览器会自动进行编码后发送给服务器。
提交方法
在表单中采用type=submit
的控件,就可以提交表单。
<form>
<input type="submit" value="提交" />
</form>
一般我们会采用button标签,直接放在form中,这样也可以提交表单。button的默认type为submit
<form>
<button>提交<button>
</form>
除此之外,我们还可以实用表单元素的submit方法,通过js提交表单。
document.querySelector('form').submit()
submit方法是来自于HTMLFormElement这个对象,而实例form元素是通过继承HTMLFormElement才得以调用。
通过reset方法可以重置所有表单的value值
document.querySelector('form').reset()
提交表单细节
上面说到在表单内有 button 控件或者有 type 为 submit 的 input 控件都可以提交表单,除此之外还有 type 为 image 的input 控件也可以用来提交表单。
<input type='image' src='xxx.jpg'/>
如果焦点在上述三种表单控件上,那么按回车键也会触发表单提交。如果没有提交按钮,那表单即使按回车键也不会触发提交按钮。
当用上面方式提交表单时,会触发一个 submit 事件,我们可以在这时候验证一下表单数据。如果此时阻止默认行为,那么就可以取消提交。
let form =document.getElementById('myform')
form.addEvemtListener('submit',(e)=>{
e.preventDefault()//取消提交
})
如果采用 submit()方法提交的话,则无需表单控件,直接 js 脚本触发,但是这个方法并不会触发 submit 事件,因此应当先进行表单验证后触发 submit 方法。
提交表单时用户可能会触发二次提交,目前已经比较好的方法是提交完之后给表单设置禁用属性,或者监听 onsubmit 事件来取消之后的表单提交。
重置表单
除了使用reset 方法重置表单外,还可以采用 type 值为 reset 的 input 控件或者 button 控件来重置表单。
<input type='reset' value='reset form'/>
<button type='reset'>reset form</button>
不管是 reset 方法还是上述两个控件,在重置表单后都会触发 reset 事件,同样的,我们可以禁止默认行为来阻止表单重置
let form =document.getElementById('myform')
form.addEvemtListener('reset',(e)=>{
e.preventDefault()//取消提交
})
FormData 对象
表单数据以键值对的形式向服务器发送,这是由浏览器自动完成的。但是有时候,我们需要自己通过 js 来完成,构造一个表单并发送给服务器。这就需要用到 formData 对象
formData 是一个构造函数,用来生成表单的实例
var formData = new FormData(form)
FormData构造函数可接收一个 DOM 的表单元素作为参数,它会自动处理表单的键值对。这个参数是可选的,如果省略,就表示一个空的表单。
new FormData() //一个空表单
如果接收一个表单元素,那么就可以获得表单元素的键值对。
<form id="myForm" name="myForm">
<div>
<label for="username">用户名:</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="useracc">账号:</label>
<input type="text" id="useracc" name="useracc">
</div>
<div>
<label for="userfile">上传文件:</label>
<input type="file" id="userfile" name="userfile">
</div>
<input type="submit" value="Submit!">
</form>
我们可以利用 FormData 来处理上面的表单。
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
formData.set('username','xxx')
formData.get('username') // xxx
for(let k of formData.keys()){
console.log(k)
}
//"username"
//"useracc"
//"userfile"
FormData提供以下方法
- FormData.get(key):获取指定键名对应的键值,参数为键名。如果有多个同名的键值对,则返回第一个键值对的键值。
- FormData.getAll(key):返回一个数组,表示指定键名对应的所有键值。如果有多个同名的键值对,数组会包含所有的键值。
- FormData.set(key, value):设置指定键名的键值,参数为键名。如果键名不存在,会添加这个键值对,否则会更新指定键名的键值。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
- FormData.delete(key):删除一个键值对,参数为键名。
- FormData.append(key, value):添加一个键值对。如果键名重复,则会生成两个相同键名的键值对。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
- FormData.has(key):返回一个布尔值,表示是否具有该键名的键值对。
- FormData.keys():返回一个遍历器对象,用于for…of循环遍历所有的键名。
- FormData.values():返回一个遍历器对象,用于for…of循环遍历所有的键值。
- FormData.entries():返回一个遍历器对象,用于for…of循环遍历所有的键值对。如果直接用for…of循环遍历 FormData 实例,默认就会调用这个方法。
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
formData.set('username','xxx')
formData.append('username','yyy')
console.log(formData.getAll('username')) //["xxx", "yyy"]
formData.append('userpic[]', myFileInput.files[0], 'user1.jpg');
formData.append('userpic[]', myFileInput.files[1], 'user2.jpg');
下面是遍历器的例子
var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
for (var key of formData.keys()) {
console.log(key);
}
// "key1"
// "key2"
for (var value of formData.values()) {
console.log(value);
}
// "value1"
// "value2"
for (var pair of formData.entries()) {
console.log(pair[0] + ': ' + pair[1]);
}
// key1: value1
// key2: value2
// 等同于遍历 formData.entries()
for (var pair of formData) {
console.log(pair[0] + ': ' + pair[1]);
}
// key1: value1
// key2: value2
表单验证
表单自身有 API 可以指定一些条件,自动进行验证。
<!-- 必填 -->
<input required>
<!-- 必须符合正则表达式 -->
<input pattern="banana|cherry">
<!-- 字符串长度必须为6个字符 -->
<input minlength="6" maxlength="6">
<!-- 数值必须在1到10之间 -->
<input type="number" min="1" max="10">
<!-- 必须填入 Email 地址 -->
<input type="email">
<!-- 必须填入 URL -->
<input type="URL">
如果一个控件通过验证,它就会匹配:valid的 CSS 伪类,浏览器会继续进行表单提交的流程。如果没有通过验证,该控件就会匹配:invalid的 CSS 伪类,浏览器会终止表单提交,并显示一个错误信息。
input:invalid {
border-color: red;
}
input,
input:valid {
border-color: #ccc;
}
checkValidity()
这个方法用来手动触发表单校验,表单元素和表单控件都有checkValidity()这个方法。
// 触发整个表单的校验
form.checkValidity()
// 触发单个表单控件的校验
formControl.checkValidity()
这个方法返回一个布尔值,true 代表通过,false 表示失败。
function submitForm(action) {
var form = document.getElementById('form');
form.action = action;
if (form.checkValidity()) {
form.submit();
}
}
willValidate 属性
控件元素的willValidate属性是一个布尔值,表示该控件是否会在提交时进行校验。
// HTML 代码如下
// <form novalidate>
// <input id="name" name="name" required />
// </form>
var input = document.querySelector('#name');
input.willValidate // true
validationMessag属性
控件元素的validationMessage属性返回一个字符串,表示控件不满足校验条件时,浏览器显示的提示文本。以下两种情况,该属性返回空字符串。
- 该控件不会在提交时自动校验
- 该控件满足校验条件
// HTML 代码如下
// <form><input type="text" required></form>
document.querySelector('form input').validationMessage
// "请填写此字段。"
下面是另一个例子
<form id="myForm" name="myForm">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
<div id="prompt"></div>
</form>
var input = document.getElementById('username')
if (!input.checkValidity()) {
document.getElementById('prompt').innerHTML = input.validationMessage;
}
setCustomValidity()
那么如果我们想指定表单验证失败后的内容,就可以使用这个 API。还是上面的例子,我们修改一下
var input = document.getElementById('username')
if (!input.checkValidity()) {
input.setCustomValidity('没填写内容无法提交噢')
document.getElementById('prompt').innerHTML = input.validationMessage;
}
已经修改掉系统自带的提示文字了
<form action="somefile.php">
<input type="text" name="username" placeholder="Username" pattern="[a-z]{1,15}" id="username" > <input type="submit"> </form>
上面的表单输入框,要求只能输入小写字母,且不得超过15个字符。如果输入不符合要求(比如输入“ABC”),提交表单的时候,Chrome 浏览器会弹出报错信息“Please match the requested format.”,禁止表单提交。下面使用setCustomValidity()方法替换掉报错信息。
var input = document.getElementById('username');
input.oninvalid = function (event) {
event.target.setCustomValidity(
'用户名必须是小写字母,不能为空,最长不超过15个字符'
);
}
上面代码中,setCustomValidity()方法是在invalid事件的监听函数里面调用。
该方法也可以直接调用,这时如果参数不为空字符串,浏览器就会认为该控件没有通过校验,就会立刻显示该方法设置的报错信息。
/* HTML 代码如下 <form> <p><input type="file" id="fs"></p> <p><input type="submit"></p> </form> */
document.getElementById('fs').onchange = checkFileSize;
function checkFileSize() {
var fs = document.getElementById('fs');
var files = fs.files;
if (files.length > 0) {
if (files[0].size > 75 * 1024) {
fs.setCustomValidity('文件不能大于 75KB');
return;
}
}
fs.setCustomValidity('');
}
上面代码一旦发现文件大于 75KB,就会设置校验失败,同时给出自定义的报错信息。然后,点击提交按钮时,就会显示报错信息。这种校验失败是不会自动消除的,所以如果所有文件都符合条件,要将报错信息设为空字符串,手动消除校验失败的状态。
validity属性
控件元素的属性validity属性返回一个ValidityState对象,包含当前校验状态的信息。
该对象有以下属性,全部为只读属性。
- ValidityState.badInput:布尔值,表示浏览器是否不能将用户的输入转换成正确的类型,比如用户在数值框里面输入字符串。
- ValidityState.customError:布尔值,表示是否已经调用setCustomValidity()方法,将校验信息设置为一个非空字符串。
- ValidityState.patternMismatch:布尔值,表示用户输入的值是否不满足模式的要求。
- ValidityState.rangeOverflow:布尔值,表示用户输入的值是否大于最大范围。
- ValidityState.rangeUnderflow:布尔值,表示用户输入的值是否小于最小范围。
- ValidityState.stepMismatch:布尔值,表示用户输入的值不符合步长的设置(即不能被步长值整除)。
- ValidityState.tooLong:布尔值,表示用户输入的字数超出了最长字数。
- ValidityState.tooShort:布尔值,表示用户输入的字符少于最短字数。
- ValidityState.typeMismatch:布尔值,表示用户填入的值不符合类型要求(主要是类型为 Email 或 URL 的情况)。
- ValidityState.valid:布尔值,表示用户是否满足所有校验条件。
- ValidityState.valueMissing:布尔值,表示用户没有填入必填的值。
var input = document.getElementById('myinput');
if (input.validity.valid) {
console.log('通过校验');
} else {
console.log('校验失败');
}
var txt = '';
if (document.getElementById('myInput').validity.rangeOverflow) {
txt = '数值超过上限';
}
document.getElementById('prompt').innerHTML = txt;
如果想禁止浏览器弹出表单验证的报错信息,可以监听invalid事件。
var input = document.getElementById('username');
var form = document.getElementById('form');
var elem = document.createElement('div');
elem.id = 'notify';
elem.style.display = 'none';
form.appendChild(elem);
input.addEventListener('invalid', function (event) {
event.preventDefault();
if (!event.target.validity.valid) {
elem.textContent = '用户名必须是小写字母';
elem.className = 'error';
elem.style.display = 'block';
input.className = 'invalid animated shake';
}
});
input.addEventListener('input', function(event){
if ( 'block' === elem.style.display ) {
input.className = '';
elem.style.display = 'none';
}
});
上面代码中,一旦发生invalid事件(表单验证失败),event.preventDefault()用来禁止浏览器弹出默认的验证失败提示,然后设置定制的报错提示框。
表单的 novalidate 属性
表单元素的 HTML 属性novalidate,可以关闭浏览器的自动校验。
<form novalidate>
</form>
这个属性也可以在脚本里设置。
form.noValidate = true;
如果表单元素没有设置novalidate属性,那么提交按钮(<button>
或<input>
元素)的formnovalidate属性也有同样的作用。
<form>
<input type="submit" value="submit" formnovalidate> </form>
enctype 属性
表单能够用四种编码,向服务器发送数据。编码格式由表单的enctype属性决定。
假定表单有两个字段,分别是foo和baz,其中foo字段的值等于bar,baz字段的值是一个分为两行的字符串。
The first line.
The second line.
下面四种格式,都可以将这个表单发送到服务器。
(1)GET 方法
如果表单使用GET方法发送数据,enctype属性无效。
<form
action="register.php"
method="get"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
数据将以 URL 的查询字符串发出。
?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.
(2)application/x-www-form-urlencoded
如果表单用POST方法发送数据,并省略enctype属性,那么数据以application/x-www-form-urlencoded格式发送(因为这是默认值)。
<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;" >
</form>
发送的 HTTP 请求如下。
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
上面代码中,数据体里面的%0D%0A代表换行符(\r\n)。
(3)text/plain
如果表单使用POST方法发送数据,enctype属性为text/plain,那么数据将以纯文本格式发送。
<form
action="register.php"
method="post"
enctype="text/plain"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
发送的 HTTP 请求如下。
Content-Type: text/plain
foo=bar
baz=The first line.
The second line.
(4)multipart/form-data
如果表单使用POST方法,enctype属性为multipart/form-data,那么数据将以混合的格式发送。
<form
action="register.php"
method="post"
enctype="multipart/form-data"
onsubmit="AJAXSubmit(this); return false;"
>
</form>
发送的 HTTP 请求如下。
Content-Type: multipart/form-data; boundary=---------------------------314911788813839
-----------------------------314911788813839
Content-Disposition: form-data; name="foo"
bar
-----------------------------314911788813839
Content-Disposition: form-data; name="baz"
The first line.
The second line.
-----------------------------314911788813839--
这种格式也是文件上传的格式。
文件上传
用户上传文件,也是通过表单。用户通过文件输入框将本地文件,提交表单的时候,浏览器就会将这个文件发送到服务器上。
<input type="file" id="file" name="myFile">
此外,还需要将表单<form>
元素的method属性设为POST,enctype属性设为multipart/form-data。其中,enctype属性决定了 HTTP 头信息的Content-Type
字段的值,默认情况下这个字段的值是application/x-www-form-urlencoded,但是文件上传的时候要改成multipart/form-data
。
<form method="post" enctype="multipart/form-data">
<div> <label for="file">选择一个文件</label> <input type="file" id="file" name="myFile" multiple> </div> <div> <input type="submit" id="submit" name="submit_button" value="上传" /> </div> </form>
上面的 HTML 代码中,file 控件的multiple属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。
var fileSelect = document.getElementById('file');
var files = fileSelect.files;
然后,新建一个 FormData 实例对象,模拟发送到服务器的表单数据,把选中的文件添加到这个对象上面。
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
// 只上传图片文件
if (!file.type.match('image.*')) {
continue;
}
formData.append('photos[]', file, file.name);
}
最后,使用 Ajax 向服务器上传文件。
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.php', true);
xhr.onload = function () {
if (xhr.status !== 200) {
console.log('An error occurred!');
}
};
xhr.send(formData);
除了发送 FormData 实例,也可以直接 AJAX 发送文件。
var file = document.getElementById('test-input').files[0];
var xhr = new XMLHttpRequest();
xhr.open('POST', 'myserver/uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
File对象
File 对象代表文件,用来读写文件信息。最常见的就是表单的上传控件,用户选中文件以后,浏览器就会生成一个数组,里面是每一个用户选中的文件,它们都是 File 实例对象。
// HTML 代码如下
// <input id="fileItem" type="file">
var file = document.getElementById('fileItem').files[0];
file instanceof File // true
上面代码中,file是用户选中的第一个文件,它是 File 的实例。
File 构造函数
我们也可以生成 File 实例对象
new File(array, name [, options])
File()构造函数接受三个参数。
-
array:一个数组,成员可以是二进制对象或字符串,表示文件的内容。
-
name:字符串,表示文件名或文件路径。
-
options:配置对象,设置实例的属性。该参数可选。 第三个参数配置对象,可以设置两个属性。
-
type:字符串,表示实例对象的 MIME 类型,默认值为空字符串。
-
lastModified:时间戳,表示上次修改的时间,默认为Date.now()。
var file = new File(
['foo'],
'foo.txt',
{
type: 'text/plain',
}
);
File 对象有以下实例属性。
- File.lastModified:最后修改时间
- File.name:文件名或文件路径
- File.size:文件大小(单位字节)
- File.type:文件的 MIME 类型
var myFile = new File([], 'file.bin', {
lastModified: new Date(2018, 1, 1),
});
myFile.lastModified // 1517414400000
myFile.name // "file.bin"
myFile.size // 0
myFile.type // ""
File 对象没有自己的实例方法,由于继承了 Blob 对象,因此可以使用 Blob 的实例方法slice()。
FileList 对象
FileList对象是一个类似数组的对象,代表一组选中的文件,每个成员都是一个 File 实例。它主要出现在两个场合。
- 文件控件节点(
<input type="file">
)的files属性,返回一个 FileList 实例。 - 拖拉一组文件时,目标区的DataTransfer.files属性,返回一个 FileList 实例。
// HTML 代码如下
// <input id="fileItem" type="file">
var files = document.getElementById('fileItem').files;
files instanceof FileList // true
上面代码中,文件控件的files属性是一个 FileList 实例。
FileList 的实例属性主要是length,表示包含多少个文件。
FileReader 对象
FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
浏览器原生提供一个FileReader构造函数,用来生成 FileReader 实例。
var reader = new FileReader();
FileReader 有以下的实例属性。
- FileReader.error:读取文件时产生的错误对象
- FileReader.readyState:整数,表示读取文件时的当前状态。一共有三种可能的状态,0表示尚未加载任何数据,1表示数据正在加载,2表示加载完成。
- FileReader.result:读取完成后的文件内容,有可能是字符串,也可能是一个 ArrayBuffer 实例。
- FileReader.onabort:abort事件(用户终止读取操作)的监听函数。
- FileReader.onerror:error事件(读取错误)的监听函数。
- FileReader.onload:load事件(读取操作完成)的监听函数,通常在这个函数里面使用result属性,拿到文件内容。
- FileReader.onloadstart:loadstart事件(读取操作开始)的监听函数。
- FileReader.onloadend:loadend事件(读取操作结束)的监听函数。
- FileReader.onprogress:progress事件(读取操作进行中)的监听函数。 下面是监听load事件的一个例子。
// HTML 代码如下
// <input type="file" onchange="onChange(event)">
function onChange(event) {
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result)
};
reader.readAsText(file);
}
上面代码中,每当文件控件发生变化,就尝试读取第一个文件。如果读取成功(load事件发生),就打印出文件内容。
FileReader 有以下实例方法。
- FileReader.abort():终止读取操作,readyState属性将变成2。
- FileReader.readAsArrayBuffer():以 ArrayBuffer 的格式读取文件,读取完成后result属性将返回一个 ArrayBuffer 实例。
- FileReader.readAsBinaryString():读取完成后,result属性将返回原始的二进制字符串。
- FileReader.readAsDataURL():读取完成后,result属性将返回一个 Data URL 格式(Base64 编码)的字符串,代表文件内容。对于图片文件,这个字符串可以用于
<img>
元素的src属性。注意,这个字符串不能直接进行 Base64 解码,必须把前缀data:/;base64,从字符串里删除以后,再进行解码。 - FileReader.readAsText():读取完成后,result属性将返回文件内容的文本字符串。该方法的第一个参数是代表文件的 Blob 实例,第二个参数是可选的,表示文本编码,默认为 UTF-8。 下面是一个例子。
/* HTML 代码如下 <input type="file" onchange="previewFile()"> <img src="" height="200"> */
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener('load', function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
上面代码中,用户选中图片文件以后,脚本会自动读取文件内容,然后作为一个 Data URL 赋值给<img>
元素的src属性,从而把图片展示出来。
表单事件
表单提交往往会有个默认刷新行为,一般我们都会使用e.preventDefault
取消。
input事件
当input、select、texttarea的值发生变化时,就会触发input事件。它的特点是,操作一次就会触发一次。连续触发。
<input id="ipt" type="text"/>
ipt.addEventListener('input',()=>{
console.log('触发了input事件')
})
上面的代码,每一次对text进行修改,就会触发input事件,执行回调函数。
<select name="" id="ipt">
<option value="1">选项一</option>
<option value="2">选项二</option>
</select>
ipt.addEventListener('input',()=>{
console.log('触发了input事件')
})
上面的select
标签同理,每次选择不同的选项,也会触发input事件,可以说input是范围比较大的表单事件,包含的内容很多,而且特点是变化后立即发生。
input 事件跟 change 事件很像,不同之处是 input 事件是元素的值发生变化后立即发生,而 change 是在元素失去焦点后发生,React 的 onChange 事件并不是原生 change 事件,特别是在受控组件上,每次值发生变化都会触发。而 Vue 的 change 事件就跟原生事件一样。
那么总结 input 跟 change 原生事件的不同之处在于:
- input 是每次值改变就会触发(连续的)
- change 是失去焦点才触发,尽管值可能已经变化多次。
select事件
select
是选中文本事件,当我们在input内选中文本时,会触发这个事件,可以通过e.target
中的value
属性拿到选中的文本
<input id="ipt" type="text">
ipt.addEventListener('select',(e)=>{
console.dir(e.target.value)
})
上面的代码直接打出了选中的文本。
选中的文本可以通过event.target
元素的selectionDirection
、selectionEnd
、selectionStart
和value
属性拿到。
change 事件
上面的input事件的特点我们已经知道了,虽然input事件非常好,但是有时候过于频繁的触发机制不太符合需求,所以我们需要用到change
事件,它的特点就是值修改完成后才会触发。
对于select标签来说,change事件基本跟input是一样的,但是input有明显的特别之处,例如
<input id="ipt" type="text">
ipt.addEventListener('change',()=>{
console.log('触发了change事件')
})
只有值完成改变并且失去焦点的时候才会触发这个事件.
change事件当<input>
、<select>
、<textarea>
的值发生变化时触发。它与input事件的最大不同,就是不会连续触发,只有当全部修改完成时才会触发,另一方面input事件必然伴随change事件。具体来说,分成以下几种情况。
- 激活单选框(radio)或复选框(checkbox)时触发。
- 用户提交时触发。比如,从下列列表(select)完成选择,在日期或文件输入框完成选择。
- 当文本框或
<textarea>
元素的值发生改变,并且丧失焦点时触发。
// HTML 代码如下
// <select size="1" onchange="changeEventHandler(event);">
// <option>chocolate</option>
// <option>strawberry</option>
// <option>vanilla</option>
// </select>
function changeEventHandler(event) {
console.log(event.target.value);
}
如果比较一下上面input事件的例子,你会发现对于<select>
元素来说,input和change事件基本是等价的。
invalid 事件
当表单提交时,如果表单的值不满足条件,那么就会触发invalid
事件。
<form>
<input type="text" required oninvalid="console.log('invalid input')" />
<button type="submit">提交</button>
</form>
上面的代码中,由于表单是必填的,当用户未填写完成但是点击提交时,就会触发invalid事件
reset 事件
reset事件当表单重置(所有表单成员变回默认值)时触发。
submit 事件
submit事件当表单数据向服务器提交时触发。注意,submit事件的发生对象是<form>
元素,而不是<button>
元素,因为提交的是表单,而不是按钮。
inputEvent 事件对象
InputEvent接口主要用来描述input事件的实例。该接口继承了Event接口,还定义了一些自己的实例属性和实例方法。
浏览器原生提供InputEvent()构造函数,用来生成实例对象。
new InputEvent(type, options)
第一个参数是字符串,表示事件名称,该参数是必需的。第二个参数是一个配置对象,用来设置事件实例的属性,该参数是可选的。配置对象的字段除了Event构造函数的配置属性,还可以设置下面的字段,这些字段都是可选的。
e.data
这个接口返回的是变动的内容。
<input type="text" id="ipt">
ipt.addEventListener('input',(e)=>{
console.log(e.data)
})
上面的代码会返回变动的文本内容,例如,在文本框中输入1,就会打印1,再输入2,就会打印2,如果此时删除,那么会返回null
e.inputType
这个接口用于输入的类型,包括以下内容:
- 手动插入文本
insertText
- 贴插入文本
insertFromPaste
- 向后删除
deleteContentBackward
- 向前删除
deleteContentForward
e.dataTransfer
InputEvent.dataTransfer属性返回一个 DataTransfer 实例。该属性只在文本框接受粘贴内容(insertFromPaste)或拖拽内容(insertFromDrop)时才有效。
今天的文章Form表单相关知识整理分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16324.html