最近捣鼓EROS框架,使用的是WEEX 0.18版本sdk。
WEEX 0.18 版本的 input 尚存在BUG,表现为当使用v-model绑定值时,还原到绑定值原始状态时,无法触发input事件,此时还影响到v-model的绑定。
拿官方的例子:
<input type="text" placeholder="Input Text" class="input" :autofocus=true value="" @change="onchange" @input="oninput"/>
methods: {
onchange: function (event) {
this.txtChange = event.value;
console.log('onchange', event.value);
},
}
然后在Android下简单的做下面的操作
- 打开输入页面,此时input框是空的
- 输入字符'a',此时出现字符a,并且成功的打印了conchange日志
- 按退格删除字符a
- 预期结果:
字符'a'被删除
打印onchange事件,value为''
实际结果:
字符'a'被删除
未打印onchange事件
如果不使用value来设置值,改使用v-model,也会出现这样的情况。当input必须输入值时,先输入字符a再删除清空,结果发现验证通过了!实际获得的输入框值还是'a'!
这个BUG影响太大了,要知道输入框可是最常见使用的组件了,还存在这么肥个BUG,够养程序员多少年?
网上搜了下,有人指出了这个BUG的一些相关的场景
https://segmentfault.com/q/1010000010238162/a-1020000010276364
里面指出了通过修改源码的方式来解决该BUG。根源在mIgnoreNextOnInputEvent
虽然觉得修改源码也可以解决,但是觉得直接修改源码还是比较入侵的做法。于是又简单过了遍源码(前人的落坑可以让我们走的更远?),发现2个线索:
- mIgnoreNextOnInputEvent是在setValue时设置true的
- mIgnoreNextOnInputEvent设置true会导致onTextChanged里出现return,无法发送事件
于是就有了解决方案1:
不执行setValue
即去掉value="",让value不进行初始化,那么就不会执行setValue,那么输入a后再删除,成功触发change事件!
这种模式适用于搜索框的处理,只需要正常触发change事件即可。
但是表单输入咋办?安卓可是没法用ref去取值的,死了死了。马上要搬起AS打PATCH。。。。
别急,还有救,下面还有方案2:
v-model初始值为undefined
再仔细看一下源码,textChange还有个return
if (mBeforeText.equals(s.toString())) {
return;
}
断章取义来看,如果很规范的程序员来写的话,应该是判断之前的数据和当前数据相等之类的处理。在这种情况下不需要发送change时间。
这让我想起了WEB开发的reset事件,重置的时候不应该触发change事件的,估计这里想模仿web的模式。如果是,那么就要找一个没有办法输入的值来作为初始值。我先找了null
<input type="text" placeholder="Input Text" class="input" :autofocus=true v-model="userName" @change="onchange" @input="oninput"/>
......
data(){
return {
userName: null
};
}
跑一下,悲剧,输入框内的值是"null"。再试了下把userName换成undefined,成了!输入a后删除能够成功触发。唯一要注意的是,提交要处理好undefined(这个json引擎会干的很好,不用担心)
较真的同学会说我没把原理讲透彻,好吧,我承认没有把源码完全看完,做了半个标题党,mIgnoreNextOnInputEvent不一定是关键,但是问题解决了,填坑完毕。等待其它程序员继续铺路。。。。。?