移动端H5输入框踩坑总结

本文介绍移动端输入框上触发的与用户输入有关的事件,总结移动端与pc端上这些事件的差别,主要关注点在事件触发的顺序、不同设备上是否会触发该事件以及事件对象包含的属性。

用户输入事件

  • keydown: 发生在键盘的键被按下的时候
  • keypress: 紧接着keydown事件触发
  • keyup:释放键盘键时触发
  • textInput:当用户在可编辑区域中输入字符时触发,发生在input事件之前
  • input:在元素值发生变化时立即触发
  • compositionstart:触发于一段文字的输入之前(通常是中文输入之前,输入完成需要一系列键盘操作)
  • compositionupdate:触发于字符被输入到一段文字的时候(输入过程中触发)
  • compositionupdate:触发于文本段落的输入完成或取消时
  • change:用户提交对元素值的更改(元素失去焦点)

以上是用户输入可能会触发的事件(pc端&移动端),在前端开发中一般想要获取用户输入的内容,最便利的方法是通过监听input元素的oninput事件,在事件处理函数中获取input元素的value属性即可。当用户输入中文字符时,在没有输入完成之前input事件不会被触发,但一般我们也不需要在中文字符输入完成之前知道用户输入了什么内容。下面是我最近遇到的问题,需求是做一个像百度输入框一样可以模糊搜索的输入框,如下图,

三星输入法百度模糊搜索.jpeg

一般手机只需要监听input事件来获取用户输入值即可,但三星手机输入法处理用户输入英文字母并非如此,在选择英文输入法的情况下,用户输入英文字母可以触发input事件,但是input元素并没有获取到用户输入的值,必须像输入中文那样点选软键盘上方的词(图中红框标记),input元素才能获取到值,也就导致在用户没有点选英文词之前都无法进行模糊搜索,不符合产品最初的设计,要做到像百度搜索那样,尝试了下面两种方法,以第一种方法为主。

利用事件对象获取输入值

  1. 监听input事件
  2. 将事件对象的data属性值手动赋值给input元素的value

上述方法完美适用于Chrome浏览器的手机模拟器,但是到移动端就不适用了,发现移动端的事件对象event中并没有data属性,并且也不包含任何反应用户输入的属性。


接着对keydownkeypresskeyuptextInput事件进行试验(由于我认为这里是英文输入,所以默认不会触发composition系列事件),试验表明移动端输入事件中只有textInput事件对象的data属性对应用户输入的值,以为终于可以解决了,在移动端上实验发现还是没有获取到,是因为三星输入法输入英文时根本没有触发textInput事件。
换一个解决思路:总有一个事件可以获取用户输入的值,于是对文章开头列出的所有事件进行监听,并打印事件对象,不同输入法输入英文字母时触发事件顺序如下:

  • 通用输入法:keydowntextInputinputkeyup
  • 三星输入法:keydowncompositionstartcompositionupdateinputkeyup
    最初被忽略的composition系列事件在三星输入法下是可以被触发的,并且compositionupdate事件对象的data属性值正是一直在找的用户输入内容,于是最终解决方案如下:
  1. 监听compositionupdate事件
  2. 将事件对象的data属性值手动赋值给input元素的value

通过documentexecCommand方法获取输入值

  1. document.execCommand('SelectAll')可以选中编辑区里的全部内容
  2. let text = window.getSelection().toString()表示用户选择的文本范围或光标的当前位置
  3. 步骤2得到的text即为用户当前输入框的内容,即使此时input元素未获取到value
  4. 将变量text的值手动赋值给input元素的value

总结

1.移动端不同输入法对用户输入的处理方法有所不同,可以理解为两大类:

  • 需要一系列键盘操作的输入,如中文输入、类似于三星输入法的英文输入,这一类输入操作一般会触发composition系列的事件,但在输入完成之前,输入框可能没有获取到用户输入
  • 直接输入,用户输入直接改变输入框的value值,这类输入在输入过程中不会触发composition系列事件

2.移动端软键盘输入与pc端键盘输入的事件差别较大,分别表现在是否会触发某些事件以及相同事件的事件对象属性也有所不同。

你可能感兴趣的:(移动端H5输入框踩坑总结)