问题所在:
在小程序开发中,官网提供的表单组件不足以满足我们的需求,所以我们需要自定义组件。这里我们以按钮
为例
需求:
1、默认按钮都不选中,当点击一个按钮选中且按钮变色,选中另一个时,上一个选中的按钮恢复之前的颜色。
2、默认按钮都不选中,点击第一个按钮有对应的事件且按钮变色,选中另一个时,按钮也变色,且前一个选中的按钮不会变化。
完成效果图:
Component({
/**
* 单选按钮组组件
*/
properties: {
// 按钮内容数组
buttonList: {
type: Array,
value: []
},
// 默认选中第一个,根据下标设置
defaultSelect: {
type: Number,
value: -1,
},
// 是否允许选中两个
all: {
type: Boolean,
value: false
},
value: String
},
/**
* 组件的初始数据
*/
data: {
// 使用的样式
lengthStyle: "",
// 记录全部样式
recordStyle: [],
// 当前选中目标
selected: -1,
display: false
},
lifetimes: {
},
observers: {
"buttonList, defaultSelect": function (buttons, choose) {
// 初始化放在此处,未找到合适的生命周期函数
if (buttons.length != 0) {
// 根据长度决定使用的样式
this._selectStyle();
// 初始化样式数组
this._initRecordStyle();
// 设置默认选中,多选不设置默认选中
if(!this.data.all){
this.setSelected(choose);
}
}
}
},
/**
* 组件的方法列表
*/
methods: {
_selectStyle: function () {
switch (this.data.buttonList[0].text.length) {
case 1:
this.setData({
lengthStyle: "onelength"
});
break;
case 2:
this.setData({
lengthStyle: "twolength"
});
break;
case 3:
this.setData({
lengthStyle: "threelength"
});
break;
default:
this.setData({
lengthStyle: "threelength"
});
}
},
_initRecordStyle: function () {
if (this.data.all) {
this.data.value = []
}
this.data.buttonList.forEach(element => {
this.data.recordStyle.push(".unselected");
if (this.data.all) {
this.data.value.push(false)
}
});
},
_setSelected: function (event) {
this.setSelected(event.currentTarget.dataset.index);
this.triggerEvent('tapor', this.data.buttonList[event.currentTarget.dataset.index], {});
},
// 只实现允许全部选中的情况
setUnselected: function (index) {
if(this.data.value[index]){
this.data.recordStyle[index] = '.unselected'
this.setData({
recordStyle: this.data.recordStyle
})
this.data.value[index] = !this.data.value[index]
}
},
setSelected: function (index) {
if (index < this.data.buttonList.length) {
// 允许全部选中
if (this.data.all) {
if(!this.data.value[index]){
this.data.recordStyle[index] = '.selected'
this.setData({
recordStyle: this.data.recordStyle
})
this.data.value[index] = !this.data.value[index]
}
return
}
// 单选
// 变更下标和当前选中下标一致,则不做处理
if (this.data.selected == index) {
return;
}
// 设置-1都不选中
if (-1 == index) {
for (let index = 0; index < this.data.recordStyle.length; index++) {
this.data.recordStyle[index] = ''
this.setData({
selected: index,
value: '',
recordStyle: this.data.recordStyle
})
}
return;
}
// 当前选中下标更改为未选中
this.data.recordStyle[this.data.selected] = ".unselected";
// 设置新的选中下标
this.data.recordStyle[index] = ".selected";
// 记录当前选中下标
// recordStyle说明:直接修改数组内容页面不会刷新,需要重新设置数组
this.setData({
selected: index,
value: this.data.buttonList[index].value,
recordStyle: this.data.recordStyle
});
} else {
throw "设置选中的下标越界"
}
},
getSelected: function () {
return this.data.value
}
}
})
{
"component": true,
"usingComponents": {}
}
<view class="container">
<block wx:for="{{buttonList}}" wx:for-index="index" wx:for-item="item" wx:key="text">
<view class="item {{lengthStyle}} {{recordStyle[index]}}" data-index="{{index}}" bindtap="_setSelected">
<view class="content {{recordStyle[index]}}">{{item.text}}view>
view>
block>
view>
.container {
background-color: #ffffff;
display: inline-flex;
}
.item {
border: 1px solid #C7C7C7;
border-radius: 6rpx;
border-radius: 6rpx;
height: 48rpx;
margin-left: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
/** 选择第一个item */
.item:nth-child(1) {
margin-left: 0rpx;
}
.content{
font-size: 24rpx;
}
.onelength{
width: 88rpx;
}
.twolength{
width: 112rpx;
}
.threelength{
width: 136rpx;
}
.selected{
color: #D1000E;
border-color: #D1000E;
}
.unselected{
color: #000000;
border-color: #C7C7C7;
}
需要我们在使用的页面先引入我们刚才创建的组件
{
"usingComponents": {
"a-or-b": "/lib/component-form/a-or-b/a-or-b"
}
}
Page({
data: {
buttonList: [
{
text: "是",
value: "3"
}, {
text: "否",
value: "5"
}
],
// 如果页面没有加defaultSelect="{{defaultSelect}}" 属性,defaultSelect: 0 不用写
defaultSelect: 0
},
// 按钮事件
ontapor: function (e) {
console.log(e);
},
})
在页面中使用该组件
<view>
<a-or-b bind:tapor="ontapor" buttonList="{{buttonList}}">a-or-b>
view>
如果想默认就选中第一个按钮,需要加上defaultSelect="{{defaultSelect}}"
属性,在data中定义defaultSelect: 0
即可。效果页面最前面已经展示过了,这里就不在展示。
如果两个按钮都想选中,需要加上all="{{true}}"
属性。效果图如下: