牵涉到表单基本上离不开checkbox
和radiobox
,现在越来越多的程序前端采用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]()