微信小程序写一个输入八位编号的输入框

首先看看我们要实现的效果

一、

效果和很多密码框一样,一个个输入。初看到这个效果感觉很简单,外层一个view,里面来8给text设置右边框为虚线,页面上就实现了效果。然后用一个input标签,定位在这个view上面。只要设置下input里面的字符间距。这里面有一个移动端也会遇到的设置字符间距问题,即是如果设置字符间距以后,input标签在输入前七个是没有问题的,当输入第八个数字的时候,因为要给光标留位置,所以整体会往前缩进,导致布局乱掉。

在小程序中抛开这个问题,小程序的input居然设置不了字符间距

二、

第一种方法pass掉,我们想想第二种方法,对,就用8个input标签,为了吸取上面的教训,先来看看小程序的input组件能不能手动设置聚焦,主要思路就是一个input标签输入完成以后马上失去焦点,让下一个input获取焦点。等等,这样切换小程序键盘会不会跟着切换?算了,试一下看看。于是又动手做了一波。

神奇的预言,效果可以实现输入和删除,可是键盘总是一闪一闪的,这用户体验会摔手机的好吧

三、

好汉不吃眼前亏,重新写过,综合两次经验,那就这样写吧,一个view把8个text包裹,先形成八个空格,然后用一个input标签定位在view,宽高都设为100%,z-index= -1,让其在view标签下面,不要被我们看到,然后输入的数字这一一映射到八个空格子里面,光标就用一个setTimeout循环显示隐藏。这样目测没什么问题了。开始动手一顿。

哈哈哈,开发这工具里面没什么问题了,效果可以实现了,用手机测试下,我去,隐藏不了,z-index没用;好我改,font-size我设置为0,还是隐藏不了;ok,那我再改,opacity我设置为:0,现在有用了吧,去,还没用。这个时候一脸懵逼

那就只能使用终极奥义,input的宽高设置为:0;现在出不来了吧,然后给外层view一个点击事件,动态的给那个不知道哪里去了的input获取焦点,然后输入数据,完成!!

最后看看源码吧,样式就不给出来了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<view >
<image></image>
<text>请输入8位电桩编号</text>
<text bindtap='scanCode'>点击扫码</text>
</view>
<view class="code_box">
<input bindinput='numberChange' type='number' maxlength='8' focus='{{focusShow}}' bindblur='{{loseBlur}}' value='{{boxCode}}'></input>
<view catchtap='showKeyboard'>
<view data-id='0'><text>{{boxcodearr[0] == "undefind" ? "" : boxcodearr[0]}}</text><text class='cursor {{focusnum == 1 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='1'><text>{{boxcodearr[1] == "undefind" ? "" : boxcodearr[1]}}</text><text class='cursor {{focusnum == 2 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='2'><text>{{boxcodearr[2] == "undefind" ? "" : boxcodearr[2]}}</text><text class='cursor {{focusnum == 3 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='3'><text>{{boxcodearr[3] == "undefind" ? "" : boxcodearr[3]}}</text><text class='cursor {{focusnum == 4 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='4'><text>{{boxcodearr[4] == "undefind" ? "" : boxcodearr[4]}}</text><text class='cursor {{focusnum == 5 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='5'><text>{{boxcodearr[5] == "undefind" ? "" : boxcodearr[5]}}</text><text class='cursor {{focusnum == 6 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='6'><text>{{boxcodearr[6] == "undefind" ? "" : boxcodearr[6]}}</text><text class='cursor {{focusnum == 7 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
<view data-id='7'><text>{{boxcodearr[7] == "undefind" ? "" : boxcodearr[7]}}</text><text class='cursor {{focusnum == 8 ? "cursor_show" : "cursor_hid"}} {{ !cousor ? "cursor_op" : ""}}'></text></view>
</view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
data: {
boxcodearr: [],
focusnum: 0,
focusShow: false,
cousor : true,
cursorMove: ""
},

// 输入电桩编号
numberChange: function (e) {
console.log(e)
var value = e.detail.value.replace(/[\D]/g, '');
var arr = value.split('');
this.setData({
boxcodearr: arr,
boxCode : value
})
this.judgeFocus();
if (this.data.boxCode.length == 8) {
this.getBoxDetail();
} else {
this.boxCodeVerify();
}
},

// 给input标签聚焦
showKeyboard : function (e) {
this.setData({
focusShow: true
})
console.log(e.target.dataset.id);
this.judgeFocus();
},

// input标签失去焦点
loseBlur : function (e) {
console.log(e)
this.setData({
focusnum: 0
})
},
// 输入框改变时设置焦点位置
judgeFocus: function () {
var arr = this.data.boxcodearr;
var num = arr.length;
if(num == 0) num = 1;
this.setData({
focusnum : num
})
},
// 光标闪动函数
flashd : function () {
var that = this;
move();
function move() {
that.setData({
cousor : !that.data.cousor
})
that.cursorMove = setTimeout(move,500);
}
}

上面写的输入框可以实现基本功能,但是,只能够从最后一个位置开始删除,每次光标都出现的第一个没有数字的框

顾客是上帝,客户说要实现点击了哪个框删,就可以单独更改那个框,好吧,那就改呗

最终方案的逻辑不变,只需要做一些简单的改动。

上面方案三的显示的数字和input的值是挂钩的,那么我们把它们分成两个不同的,互相不影响。用光标的位置来对应每个框相应的值改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 输入电桩编号
numberChange: function (e) {
console.log(e);
var value = e.detail.value.replace(/[\D]/g, '');
var arr = this.data.boxcodearr;
var focusnum = this.data.focusnum;
var boxCode = this.data.boxCode;
if (value.length > boxCode.length) {
var num = value[value.length - 1];
console.log(num);
if (arr[focusnum - 1] == "") {
arr[focusnum - 1] = num;
this.judgeFocus(true);
} else {
this.judgeFocus(true,true);
}
} else {
if (arr[focusnum - 1] == "") {
this.judgeFocus(false);
} else {
arr[focusnum - 1] = "";
this.judgeFocus(false, true);
}
value == "" ? value = "520" : value;
}
console.log(value)
this.setData({
boxCode: value,
boxcodearr: arr
})
this.judgeGet(arr);
},
// 输入框改变时,判断光标的位置
judgeFocus: function (add, noChange) {
var focusnum = this.data.focusnum;
if (add) {
focusnum++;
focusnum >= 8 ? focusnum = 8 : focusnum;
} else {
if (!noChange) {
focusnum--;
focusnum <= 1 ? focusnum = 1 : focusnum;
}
}
console.log(focusnum);
this.setData({
focusnum: focusnum
})
},
// 当输入八位输入框都满了的时候,调用接口
judgeGet(arr) {
var use = true;
for (var i = 0; i < arr.length; i++) {
if (arr[i] == "") {
use = false
}
}
if (use) {
this.getBoxDetail();
} else {
this.boxCodeVerify();
}
}