今天讲的这个问题,平常都可能碰到,但是却很容易忽视的一个问题。为了更清楚的阐述问题,我把实际的情况做了一下简化:

问题描述

在一个表单里,有一些输入框,这些输入框需要请求接口验证它们的内容是否正确,返回的结果告知用户的输入是否合法,如果合法就显示返回结果,如果不合法,会有错误提示。同时表单上还有一个提交按钮,会把你输入的合法的内容进行提交。

假设一个人在某个输入框中输入了一半(还没有失去焦点),然后直接去点击提交按钮,会发生什么情况?

表单提交时输入框失焦异步请求 gif 表单提交时输入框失焦异步请求

我们可以看到,如果在输入框未失焦的情况下,直接点击按钮,会同时触发输入框的失焦事件和提交方法。

此时失焦事件请求的结果是正确还是错误我们无从得知,万一是一个错误的数据,传到后台,而后台又没有做相关处理,就很容易引发bug。

因此为了降低错误的可能性,我们设想最好的就是先去请求失焦事件,等到结果,如果结果没问题,我们再进行提交;如果返回错误,我们就提示错误,不提交。

改造

1.首先我们要把提交按钮的click事件改成ontouchstart事件(电脑上改成mousedown事件),这样当点击提交按钮的时候,可以保证焦点在输入框上。

2.然后我们要用document.activeElement来获取当前有焦点的元素,通过识别tagName和className来确定元素。

3.我们用triggerHandler去主动触发对应的事件方法,并传递一个回调,就是放失焦方法判断当前是否成功,如果成功了,就调用回调进行提交。大概看起来像这样:

同时事件里面多了一个callback,并判断在成功的时候调用callback:

然而这样并不够,因为失焦方法会执行两次,为什么会执行两次呢?很简单,因为我们用triggerHander主动触发了一次!

也就是说,我们用triggerHander主动执行后,接着真正的失焦方法就执行了。那能不能用ev.stopProgation()或者ev.preventDefault()去阻止默认失焦方法执行呢?答案是不行,因为ev.stopProgation()/ev.preventDefault()只能阻止自己(按钮事件)方法的传递,管不到别人输入框的失焦方法。这种问题在之前的 mouseup模拟drag与click事件冲突中有提到过解决方案。

解决方法就是在用triggerHandler主动触发后设置一个变量,200ms后恢复,因为默认的失焦事件方法是紧接着就执行的,因此速度非常快,基本上在200之内,此时变量没有恢复,我们不执行就好了。

最后来看看修复好了的吧:

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字