checkbox限制选中数量

牵涉到表单基本上离不开checkboxradiobox,现在越来越多的程序前端采用vue来编写,就连小程序,小程序内部帮我们提供好了代码,但是需要限制选中个数,就要进行二次加工了。

修改官方代码示例

官方代码地址:https://developers.weixin.qq.com/miniprogram/dev/component/checkbox.html

我们着重看切换方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
checkboxChange(e) {
console.log('checkbox发生change事件,携带value值为:', e.detail.value)
const items = this.data.items
const values = e.detail.value
for (let i = 0, lenI = items.length; i < lenI; ++i) {
items[i].checked = false

for (let j = 0, lenJ = values.length; j < lenJ; ++j) {
if (items[i].value === values[j]) {
items[i].checked = true
break
}
}
}

this.setData({
items
})
}

其实解决方法很简单,e.detail.value保存的是我们选中的数据,我们判断下他长度就可以了,比如我们限制最多选3个。

修改后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
checkboxChange(e) {
console.log('checkbox发生change事件,携带value值为:', e.detail.value)
const items = this.data.items
const values = e.detail.value
// 如果长度大于3,直接删除第一个选中的
if(values.length>3){
values.shift()
}
for (let i = 0, lenI = items.length; i < lenI; ++i) {
items[i].checked = false

for (let j = 0, lenJ = values.length; j < lenJ; ++j) {
if (items[i].value === values[j]) {
items[i].checked = true
break
}
}
}

this.setData({
items
})
}

看似没什么问题,甚至测试几次也没发现有异常,但是你如果从下往上选择就发现很大的问题了。

比如选项依次为:中国,美国,俄罗斯,加拿大,韩国,日本。如果你选择的是加拿大、韩国和日本,再尝试点击中国、美国、俄罗斯中的任意一个,发现无效,并没有删除第一个,而添加进来新点击的选项。

此时观察下输出e.detail.value,我们点击中、美、俄,发现e.detail.value里存的就是中美俄,我们依次点击俄美中,e.detail.value中存的还是中美俄,也就是说人根本不按我们点击的顺序来依次保存选项,所以会出现选中三个再选上面的没反应了,因为上面的加在第一个了然后直接又被删除掉了。不管他们基于什么这样写的,我们就按照自己的逻辑写一个。

自定义方案

我们看下wxml可以看出他们的点击事件挂载到了checkbox-group组件上,并不是绑定到checkbox-item上,我们按照自己的逻辑就绑定到每个选项上。

直接上代码,wxml部分(我这里使用的uni-app,跟原生小程序相差不大):

1
2
3
4
5
6
7
<checkbox-group class="block" name="purpose_abroad">

<view class="cu-form-group" @click="checkboxChange(index)" v-for="(item, index) in purpose_abroad" :key='index'>
<view class="title">{{item.value}}</view>
<checkbox :class="item.checked?'checked':''" :checked="item.checked" :value="item.value"></checkbox>
</view>
</checkbox-group>

我的逻辑是点击该项,会把该项在选项列表中对应的索引带到函数中,我们在函数中根据该索引提取其值和样式控制。

js部分,包含数据项

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
64
65
66
export default {
data() {
return {
purpose_abroad: [{
value: '子女教育',
checked: false
}, {
value: '环境与健康',
checked: false
}, {
value: '税务筹划',
checked: false
}, {
value: '出行自由',
checked: false
}, {
value: '海外资产配置',
checked: false
}, {
value: '财富传承',
checked: false
}, {
value: '海外创业',
checked: false
}, {
value: '其他',
checked: false
}],
purpose_abroad_result: [],
}
},
methods: {
// 出国目的
checkboxChange(index) {
// 判断是否已选中3项了
if (this.purpose_abroad_result.length > 2) {
// 删除结果中第一个选中的项
var deleted_item = this.purpose_abroad_result.shift()
// 循环选项列表,一一比对,找出第一项在想选列表中的索引,修改其选中状态
for (var i = 0; i < this.purpose_abroad.length; i++) {
// 判断该项是否是要删除的项
if (this.purpose_abroad[i].value == deleted_item) {
this.purpose_abroad[i].checked = false
break
}
}
}
// 判断当前选项是否已被选
if (this.purpose_abroad[index].checked) {
// 如果当前项已被选中,则取消选中
this.purpose_abroad[index].checked = false
// 并将该选中值从结果中删除
// 找出该项在结果中的索引
this.purpose_abroad_result.splice(this.purpose_abroad_result.indexOf(this.purpose_abroad[index].value), 1)

} else {
// 选中该项
this.purpose_abroad[index].checked = true
// 将该项添加至结果中
this.purpose_abroad_result.push(this.purpose_abroad[index].value)
}

},

}
}

展示效果:

img