超级面板
文章目录
最新文章
最近更新
文章分类
标签列表
文章归档

JavaScript 常用事件之表单事件

和表单元素相关的事件有:changeinputcompositionstart/compositionupdate/compositionendfocusin/focusfocusout/blursubmit

change

change 事件可以被 <input><textarea><select>checkbox/radio 元素触发,.

注意,对于文本输入内容的改变,也就是说在文本域(input、textarea)输入内容时候,该事件不会触发,直到当文本元素失去焦点 时,触发该事件。

对于 <select>checkbox/radio 则只要发生变化就能正常触发该事件。

input

这个事件和上一个事件相似也是处理表单元素的变化:当 <input><textarea><select> 元素的值更改时,input 事件会同步的触发。

如果想要处理 <input><textarea> 的每个修改,那么这个事件是最好的:

<!-- 每次修改,并不会弹出对话框,直到该元素失去焦点才弹出 -->
<input type="text" onchange="alert(this.value)" />

<!-- 每次修改,即弹出对话框,并且弹出动作发生在元素改变之前 -->
<input type="text" oninput="alert(this.value)" />

而对于 checkbox/radio 元素,当用户单击控件时,input 事件不会触发,因为 value 属性没有更改。

<!-- 每次修改,并不会弹出对话框,直到该元素失去焦点才弹出 -->
<input type="checkbox" onchange="alert('Everytime click, This will alert current value:' + this.value)" />

<!-- 每次修改,即弹出对话框,并且弹出动作发生在元素改变之前 -->
<input type="checkbox" oninput="alert('This will never alert!!!')" />

一些键盘事件如 keyupkeypress 也可以用来监控文本的改变,但是键盘事件对于控制键,比如 CtrlShift 等也会触发。

注意:这个事件的 Cancelable 值为 false。因此无法取消,event.preventDefault() 不起作用。

compositionstart、compositionupdate、compositionend

当我们在使用 input 或者 keyup 事件监控用户的输入的时候,当用户的输入语言是中文的时候,会出现一些问题,比如用户输入“事件”,如果我们监控了 input 事件,则实际上会导致了多次触发事件,比如下面这个例子:

用户使用中文输入法输入 “shijian” 并选中 “事件” 词语,控制台会打印以下结果:

ele.addEventListener('input', function (e) {
console.log(value);
});

// s
// sh
// shi
// shij
// shiji
// shijia
// shijian
// 事件

如果我们根据用户的输入实时向服务端查询数据,则发出了多个无效查询,这堆拼音并不是我们想要查询的内容,我们想要处理的输入文本是“事件”,这个时候,这几个事件就派上了用场。

首先看一下这三个事件在 MDN 的描述:

  • compositionstart:事件触发于一段内容的输入之前(类似于 keydown 事件,但是该事件仅在若干可见字符的输入之前,而这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词。
  • compositionupdate:事件触发于内容被输入到一段文字的时候(此时类似于 input 事件,这些可见字符的输入可能需要一连串的键盘操作、语音识别或者点击输入法的备选词)。
  • compositionend:事件触发于一段文字的输入之后。

再来看一下事件触发顺序:

ele.addEventListener('keydown', function (e) {
console.log('keydown');
});
ele.addEventListener('keyup', function (e) {
console.log('keyup');
});
ele.addEventListener('compositionstart', function (e) {
console.log('compositionstart');
});
ele.addEventListener('compositionupdate', function (e) {
console.log('compositionupdate');
});
ele.addEventListener('compositionend', function (e) {
console.log('compositionend');
});
ele.addEventListener('input', function (e) {
console.log('input');
});

// 当开始输入中文的时候,触发一次 compositionstart:
// keydown
// compositionstart
// compositionupdate
// input
// keyup
// 输入中间字符,循环开始
// keydown
// compositionupdate
// input
// keyup
// 输入最后一个字符,循环结束,注意 compositionend 事件是在 input 之后 keyup 之前触发。
// keydown
// compositionupdate
// input
// compositionend
// keyup

知道了这些内容,这样我们就可以这样解决上面的问题:

function inputListener(ele, callback) {
let inputing = false;
elem.addEventListener('compositionstart', function (e) {
inputing = true;
});
elem.addEventListener('compositionend', function (e) {
inputing = false;

// compositionend 事件在 input 事件之后触发,所以需要在此调用事件处理用户输入
// 如果是处理 keyup 事件,由于 keyup 事件在 compositionend 之后触发,则不要调用 callback
callback(e);
});
elem.addEventListener('input', function (e) {
if (inputing) return;
callback(e);
});
}

inputListener(ele, function (e) {
console.log(value);
});

// 使用中文输入法输入 “shijian” 并选中 “事件” 词语,控制台会打印以下结果
// 事件

focusin、focus 与 focusout、blur

当元素获得焦点的时候可以触发 focusinfocus,两者不同之处在于 focusin 事件冒泡 focus 事件不冒泡,而同理,元素失去焦点的时候可以触发 focusoutblur,两者不同之处在于 focusout 事件冒泡 blur 事件不冒泡。

注意,并不是所有元素都支持这几个事件的。

submit

执行提交表单的行为触发的事件。

触发表单事件有三种方式:

  • 点击 <input type="submit"><input type="image"> (type="image" 是图形的提交按钮)
  • 在表单域按(input,textarea 等) Enter
  • 调用 form.submit()

使用 event.preventDefault() 可以阻止数据被提交。

注意,在表单元素使用 Enter 提交表单的时候,会触发提交按钮的上的一个点击事件,尽管并没有发生点击:

<form>
<input type="text" value="Focus here and press enter.">
<input type="submit" value="Submit" onclick="alert('click event triggered')">
</form>