想做一个简单的效果,如图示:

用户选择第一二项时,文本框是禁止状态,并显示预定义的文本;选择第三项时,清空文本并取消禁止状态,用户可以输入文本。如果用户输入文本之后又选择了第一二项,则仍然在文本框中显示预定义文本。最后提交时,获得的是文本框中的内容。
代码超级简单,定义两个变量分别代表文本框是否禁止输入和文本框的内容,在radia-group的change事件中使用setData方法改变这两个变量的值,微信就会重新渲染页面:
/**
* 退款原因改变
*/
reasonChange: function(e){
this.setData({
disableInput: e.detail.value != '',
drawbackReason: e.detail.value
})
}
/**
* 输入退款原因
*/
inputReason: function(e){
this.setData({
words: e.detail.value.length,
drawbackReason: e.detail.value,
})
},
WXML:
<view>
<view>退款原因</view>
<radio-group class='align-right' bindchange="reasonChange">
<label class="radio">
<radio value="不想投放了" color='{{styleInfo.color}}' checked="true" />
不想投放了
</label>
<label class="radio" >
<radio value="多次审核未通过" color='{{styleInfo.color}}'/>
多次审核未通过
</label>
<label class="radio" >
<radio value='' color='{{styleInfo.color}}'/>
其它({{words}}/50字)
</label>
</radio-group>
<textarea disabled='{{disableInput}}' focus='{{!disableInput}}' bindinput='inputReason' maxlength='50' value='{{drawbackReason}}'></textarea>
</view>
在微信开发工具中调试没有任何问题,在真机上调试时发现,当用户输入文本后又重新选择第一二项时,文本框中的内容不会改变,必须再选择一次第一二项,才会出现预期的效果。具体来说,就是选择第三项,输入文本“test”,然后再选择第一或第二项,文本框变成禁止状态,但文本内容仍然是“test“,这时再选择一下第一项或第二项,又恢复正常了。
反复查看代码和业务逻辑,都找不到任何问题,关键是在微信开发工具中调试是没有任何问题的。
无奈之下,查阅微信的开发文档,发现textarea的文档中有这么一句话:该组件是原生组件,使用时请注意相关限制。
什么限制呢?点链接进去继续看:
在工具上,原生组件是用web组件模拟的,因此很多情况并不能很好的还原真机的表现,建议开发者在使用到原生组件时尽量在真机上进行调试。
也就是原生组件在开发工具中的表现和真机中不尽相同,因此才会出现上面的奇怪现象。
在reasonChange和inputReason两个方法中用console.log()观察执行情况,会发现改变选项时,先触发reasonChange方法,然后又触发了inputReason方法。
经过分析就明白,在reasonChange中,使用setData方法改变了drawbackReason变量的值,此时drawbackReason的值的确变成了空字符串,而setData方法会同步更改wxml,因此同时更改了textarea的value,而更改textarea的value又会触发inputReason,这个方法中会用textarea的value去更新drawbackReason,此时textarea的value还是原来的值,这一轮代码运行下来,就造成了drawbackReason的值没有任何改变。
对微信小程序的组件没有深入研究过,我猜测对原生组件textarea,任何方式产生的文本改变都会引发bindinput事件,而在开发工具中是用web组件模拟的textarea,只有输入文本才会触发bindinput事件,用代码改变文本则不会触发。
找到原因后,解决就很简单了,添加一个变量,在reasonChange中根据用户选项设定变量的值,在inputReason中根据该变量的值决定是否反向更新drawbackReason的值。
/**
* 退款原因改变
*/
reasonChange: function(e){
//和wxml无关,无需使用setData方法
this.data.inputting = e.detail.value == ''
this.setData({
disableInput: e.detail.value != '',
drawbackReason: e.detail.value
})
},
/**
* 输入退款原因
*/
inputReason: function(e){
this.setData({
words: e.detail.value.length,
})
if(this.data.inputting){
this.setData({
drawbackReason: e.detail.value,
})
}
},
网友评论