在做某个功能开发时,由于使用系统键盘输入找一些符号比较耗时,为了优化用户体验,我们在输入框下面提供一些快捷辅助按钮,这些按钮就是特殊符号。但是在做的过程中遇到获取光标位置的问题,因为我们需要在用户点击按钮时,在光标位置处插入特殊符号。
微信小程序如何获取input光标的位置
在官方文档中推荐了一种方式,就是通过bindinput监听输入改变,在bindinput中可以获取到新的光标位置。
<input value="{{inputValue}}"
bindinput="bindInputChange"/>
bindInputChange: function (e) {
const value = e.detail.value
const cursorPos = e.detail.cursor
then.setData({
inputValue: value,
curCursorPos: cursorPos
})
}
- cursorPos就是光标的位置。
但是,这只有在用户输入时,才能拿到光标。对于input失去焦点后,用户点击input重新获取焦点,怎么获取光标位置?
这个时候可以通过bindfocus监听input获取焦点事件,结合wx.getSelectedTextRange方法来获得光标位置。
<input value="{{inputValue}}"
bindinput="bindInputChange" bindfocus="handleFocus"/>
handleFocus: function (e) {
const then = this
wx.getSelectedTextRange({
complete: res => {
then.setData({
curCursorPos: res.start
})
}
})
}
另外,当用户点击我们提供的按钮时,此时input会失去焦点,我们在处理辅助按钮的点击逻辑中会修改input的value,修改value后,用户点击input组件重新获取焦点时,光标还是在原来的位置。
例如:
原来input的value是:“40%✖️8”,光标位置在8的后面。
用户点击“➗”按钮,input的value变成:“40%✖️8➗”,理想情况下,用户点击input重新获取焦点时,光标位置应该在➗的后面,但实际上还是在8的后面。
怎么办呢?
我们在修改input的value的时候,是在当前光标位置处插入符号,插入后,光标位置应该+1。只是微信小程序没有提供一个可以修改光标位置的api。
要让修改的光标位置生效,需要使用input的focus+cursor属性配置在获取焦点时设置光标位置。
<input value="{{inputValue}}"
bindinput="bindInputChange"
focus="true" cursor="{{curCursorPos}}"
bindfocus="handleFocus"/>
微信小程序如何监听光标位置改变
前面我们获取光标都是在input有输入的情况下,或者input获取到焦点的时候。
但是,如果用户获取到焦点之后,没有输入,而是移动光标,那就获取不到移动后的光标位置了。
例如,input当前输入内容“40%✖️8”,用户点击获取焦点时,光标位置在8的后面。然后用户移动光标位置到%的后面,因为用户想要在%后面输入内容,这个时候是没有api支持监听到用户移动了光标的。
那么怎么获取呢?
有个不推荐的方式可以获取到。
因为用户移动光标后,如果输入内容,那么我们就可以通过bindinput获取到新的光标位置,如果没有输入内容,而是点击了我们提供的辅助按钮,这个时候input会失去焦点,我们可以利用bindblur获取失去焦点时的光标位置。
<input value="{{inputValue}}"
bindinput="bindInputChange"
focus="true" cursor="{{curCursorPos}}"
bindfocus="handleFocus"
bindblur="handleBlur"/>
handleBlur: function (e) {
this.setData({
curCursorPos: e.detail.cursor
})
},
但实际真机测试发现,辅助按钮的点击事件处理逻辑在handleBlur之前执行了,于是我想到了延迟处理点击事件。
handleKeyboardTap: function (e) {
new Promise(resolve => {
setTimeout(() => {
resolve();
}, 100); // 延迟100ms,100ms用户几乎无感知
}).then(() => {
// 在这里执行辅助按钮的点击事件处理逻辑
})
}
遗留问题
怎么在处理按钮点击事件的同时,input不会失去焦点呢?这样用户就不会每次点击辅助按钮之后,都要再点击一次input获取输入焦点了。