真正开发过小程序的开发者会发现,小程序里面的单选框和多选框封封装的实在不够友好,一般与UI都会有比较大的出入,所以下面来探讨一下单选框和多选框的封装。
效果
比如我们要做一个这种样式的单选框和多选框组件,我们改怎么去处理呢?
代码
wxml
<!-- 判断某个元素是不是指定数组内 -->
<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
.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
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
的内容。
个人博客:午后南杂