likes
comments
collection
share

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

作者站长头像
站长
· 阅读数 12

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

每天一个知识点

最近在给公司的一个老微信小程序项目进行维护,本人以前也没怎么接触过小程序开发,大概看了看原来的代码就上手了。

很快,一天不到,就开发了一个像模像样的页面,主要交互部分就是这个【搜索框 + 搜索按钮】,很常见的功能逻辑。

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

问题发现

但是,很快哈,非常快,刚上线,就被测试逮到,提了一个问题: 第一次搜索不对,第二次搜索就对了。

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

我心想这什么鬼啊?仔细询问了下,得知,具体复现如下:

  1. 点击输入框,拉起手机键盘,输入关键字,如我们输入“国务院”。
  2. 此时直接点击查询按钮。
  3. 展现的结果没有变化,还是全部文章,并没有过滤。

问题解决探索

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

既然知道了稳定复现步骤,我直接打开【微信开发者工具】,进行复现。

But,没有复现啊~

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

我一度怀疑是收集问题,因为测试用的 iPhone 手机测试的,但是谨慎的我还是先使用自己的手机再来一次测试。

很奇怪的是,在反复几次测试下,我发现我的手机(Android)也会不定的出现这个问题。

使用开发者工具的真机调试,能够看到,出现无法过滤的问题情况下接口的请求字段没有更新:

name字段还是空的,而非我们输入的 "国务院"

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

基于此,我想到了是不是由于微信事件的触发顺序导致的?

一些热知识:

微信小程序原生语言下,实现数据双向绑定需要使用 事件监听 + this.setData({...}) (这一点与 React 类似)。

而我们的搜索输入框数据双向绑定事件使用了 bindblur 进行监听【这里起初是为了节约一点点性能来着】。

按钮则是使用了 bindtap 监听。

基于上述的知识,我分别在 bindblurbindtap 两个监听处理函数中进行 log,最终发现果然,当错误发生时, bindtap 的log 要先于 bindblur

就这样,我发现了为什么过滤无效的直接原因,但目前还有一个问题——“为什么时而行时而不行?”

反复复现测试

带着这个问题,我反复进行了复现,最终被我发现了一个很有趣的现象:

如下图,当在手机键盘不手动收起的情况下,直接点击查询按钮,就必定会触发这个事件顺序触发错误的问题

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

而当我们手动点击收起键盘,等键盘收起后(即输入框失焦后),再点击查询按钮,则没有问题一切正常。

破案了

就这样,最终的疑惑也解决了,根本原因就在于,小程序下bindblurbindtap的事件顺序是这样的:

点击输入框外的其他控件:

先触发被点击控件的 bindtap 事件 -> 再收起键盘 -> 再触发输入框的 bindblur 事件

想要解决这个问题也很简单,我们直接将 bindblur 替换成 bindinput 在每次输入的时候都进行同步就可以了

    <input bindinput="handleInput" />
    <view bindtap="search">搜索</view>

发散测试

在小程序上我们发现了这个问题,那么原生的 html + js 是否也会在移动端下存在这个问题呢?

我构造了一个小demo进行测试:

PC上显然是没问题的

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

使用手机试一下,也没有问题,按照我们预想的先 onbluronclick 触发了(即使触发onclick时,在UI上input还没失焦,但实际上 onblur 已经触发了,将数据同步了)

微信小程序踩坑 - 1: 输入框 + 按钮 事件绑定配合问题

结论: 故此,可以得出结论,这个 blur 和 click/tap 的先后顺序问题,只有小程序上存在,H5不需要关心。而小程序请尽量使用 bindinput 来绑定 input