真正开发过小程序的开发者会发现,小程序里面的单选框和多选框封封装的实在不够友好,一般与 UI 都会有比较大的出入,所以下面来探讨一下单选框和多选框的封装。
效果

比如我们要做一个这种样式的单选框和多选框组件,我们改怎么去处理呢?
代码
wxml
html
<!-- 判断某个元素是不是指定数组内 -->
<wxs module="checkbox">
var checkStatus = function (arr, item) { return arr.indexOf(item) >= 0 };
module.exports.checkStatus = checkStatus;
</wxs>
<view hidden="{{isHidden}}">
<!-- 单选组件 -->
<radio-group
class="radio-group"
bindchange="radioChange"
wx:if="{{selectType == 'radio'}}"
>
<label
class="{{radioIndex == item.index ? focusRadioClass : initRadioClass}}"
wx:for="{{radioData}}"
wx:key="{{index}}"
id="{{item.index}}"
>
<view class="item-index">
<radio
style="opacity: 0"
value="{{item.index}}"
checked="{{item.checked}}"
/>
<view class="index">{{item.index}}</view>
</view>
<view class="flex-item text-center">{{item.value}}</view>
</label>
</radio-group>
<!-- 多选组件 -->
<checkbox-group
class="checkbox-group"
bindchange="checkboxChange"
wx:if="{{selectType == 'checkbox'}}"
>
<label
class="{{checkbox.checkStatus(checkboxIndexArr, item.index) ? focusCheckboxClass : initCheckboxClass}}"
wx:for="{{checkboxData}}"
wx:key="{{index}}"
id="{{item.index}}"
>
<view class="item-index">
<checkbox
style="opacity: 0"
value="{{item.index}}"
checked="{{item.checked}}"
disabled="{{checkboxIndexArr.length > maxLength - 1 && !checkbox.checkStatus(checkboxIndexArr, item.index)}}"
/>
<view class="index">{{item.index}}</view>
</view>
<view class="flex-item text-center"> {{item.value}} </view>
</label>
<view>{{checkboxIndexArr.prototype}}</view>
</checkbox-group>
</view>wxss
css
.flex-wrapper {
display: flex;
}
.flex-item {
flex: 1;
}
.text-center {
text-align: center;
}
.radio-group,
.checkbox-group {
margin: 0 auto;
width: 490rpx;
}
.radio-group label,
.checkbox-group label {
margin-bottom: 50rpx;
height: 68rpx;
line-height: 68rpx;
border: 1rpx solid #000;
border-radius: 10rpx;
font-size: 30rpx;
color: #000;
}
.radio-group label.active,
.checkbox-group label.active {
background-color: #fcc919;
}
.radio-group label .item-index,
.checkbox-group label .item-index {
position: relative;
flex: 0 0 40rpx;
margin: 0 0 0 20rpx;
width: 40rpx;
height: 68rpx;
}
.radio-group label .item-index .index,
.checkbox-group label .item-index .index {
position: absolute;
top: 0;
bottom: 0;
left: 0;
margin: auto;
width: 40rpx;
height: 40rpx;
overflow: hidden;
line-height: 40rpx;
text-align: center;
border-radius: 50%;
background-color: #fff;
}javascript
js
Component({
// 组件的属性列表
properties: {
selectType: {
type: String,
value: "checkbox",
},
radioData: {
type: Array,
value: [],
},
checkboxData: {
type: Array,
value: [],
},
isHidden: {
type: Boolean,
value: false,
},
maxLength: {
type: Number,
value: 2,
},
},
// 组件的初始数据
data: {
initRadioClass: "radio flex-wrapper flex-direction-row",
focusRadioClass: "radio flex-wrapper flex-direction-row active",
initCheckboxClass: "checkbox flex-wrapper flex-direction-row",
focusCheckboxClass: "checkbox flex-wrapper flex-direction-row active",
radioIndex: null,
checkboxIndexArr: [],
},
// 组件的方法列表
methods: {
// radio选择改变触发的函数
radioChange: function (e) {
let value = e.detail.value;
this.setData({
radioIndex: value,
});
this.triggerEvent("radioChange", value);
},
// checkbox选择改变触发的函数
checkboxChange: function (e) {
let value = e.detail.value;
this.setData({
checkboxIndexArr: value,
});
this.triggerEvent("checkboxChange", value);
},
},
});分析
其中,单选框比较简单,重点在于多选框。其中比较坑的地方就是需要手动来控制 checkboxIndexArr 的内容。
小程序多选框 在选中后会返回一个所选中的 value 的数组
checkboxIndexArr,所以我们自定义的样式需要通过判断当前框的value是不是在checkboxIndexArr中(切记,checkboxIndexArr 中的每个值的类型都是 String), 小程序在 wxml 中绑定方法时没办法携带参数的,所以需要需要将这个函数写在wxs中。如果需要有默认选中,需要单独把默认选中的框的样式激活,同时手动将默认选中的框的 checked 设置为
true,并将其value放入checkboxIndexArr中。如果需要做全选和全不选,需要在放置一个变量
checked,Boolean 属性,通过控制checked开控制是否全选,但是,还是需要手动 来添加和清空checkboxIndexArr的内容。如果需要做反选功能,需要在数据中单独设置一个控制 是否选中的 checked 属性,通过改变数据 checked 的值来改变多选框的选中效果,与上面一样,还是要手动 来添加和清空
checkboxIndexArr的内容。