本章实现小程序单选框组件的封装,使用radio及radio-group组件实现单选框,封装数据加载过程,并自动实现数据解析及生成,实现相应方法。
另外还提供小程序开发基础知识讲解课程,包括小程序开发基础知识、组件封装、常用接口组件使用及常用功能实现等内容,具体如下:
1. CSDN课程: https://edu.csdn.net/course/detail/37977
2. 51CTO课程:https://edu.51cto.com/course/100044719.html
3. B站视频合集:https://www.bilibili.com/video/BV13A411f7hN/
4. 西瓜视频合集:https://www.ixigua.com/7188178861195002407
5. 百度视频合集:https://baijiahao.baidu.com/builder/preview/s?id=1754693753661777020
一、背景介绍
小程序提供了单选框组件,但是大部分情况下选项数据都是需要从后端进行网络加载的,所以对单选框组件进行封装,实现多选组件及数据加载的封装。
二、源码下载
三、效果预览
四、开发视频
微信小程序原生开发功能合集之列表选择组件封装第十节:单选框组件实现
五、组件规划
封装小程序的单选框的相关功能封装,具体实现的功能如下:
1. 根据指定数据自动生成单选框组件。
2. 组件数据的双向绑定实现。
3. 数据远程加载的封装及自动处理。
5.1组件参数
参数 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
extraPama | Object | 需要从远程加载数据时的额外参数。 | ||
searchPama | string | 否 | 搜索时的搜索参数 | |
serverCodeName | string | code | 否 | 服务器返回数据的编码标识 |
serverMsgName | string | msg | 否 | 服务器返回数据的消息标识 |
serverDataName | string | data | 否 | 服务返回的数据标识 |
datas | Array | [] | 否 | 要选择的数据选项 |
url | String | 是 | 开发者服务器地址 | |
header | Object | 否 | HTTP 请求 Header,Header 中不能设置 Referer | |
timeout | Number | 否 | 超时时间,单位为毫秒 | |
value | String | 否 | radio标识,选中时触发radio-group的 change 事件,并携带 radio的 value | |
disabled | Boolean | false | 否 | 是否禁用 |
color | String | #09BB07 | 否 | radio的颜色,同 css 的color |
extraPama | Object | 否 | 数据请求时的参数 | |
method | String | GET | 否 | HTTP 请求方法:OPTIONS HTTP 请求 OPTIONS GET HTTP 请求 GET HEAD HTTP 请求 HEAD POST HTTP 请求 POST PUT HTTP 请求 PUT DELETE HTTP 请求 DELETE TRACE HTTP 请求 TRACE CONNECT HTTP 请求 CONNECT |
dataType | String | json | 否 | 返回的数据格式:json 返回的数据为 JSON,返回后会对返回的数据进行一次 JSON.parse其他 不对返回的内容进行 JSON.parse |
range-key | String | 否 | 当 range 是一个 Object Array 时,通过 range-key 来指定 Object 中 key 的值作为选择器显示内容 | |
range-id-key | String | 否 | 对象数据用于辨识的字段 | |
pamaCreator | Function | 否 | 数据请求参数回调函数 |
5.2组件事件
事件 | 参数 | 说明 |
---|---|---|
bindcancel | 取消选择时触发 | |
bindchange | value | value 改变时触发 change 事件,event.detail = {value} |
bindLoadEnd | 远程加载数据时数据加载完成时触发 |
5.3组件方法
方法 | 参数 | 说明 |
---|---|---|
loadData | Object | 重新加载数据,参数为加载数据时的额外参数,可以不传。 |
setValue | Object | 设置选中的值,mode不同时参数不同 |
getValue | Object | 获取选中的值,mode不同时返回的内容不同 |
六、代码实现
1.模板代码
<wxs module="utils">
/**
*检测itemValue数据是否在valueIndex中选中
*/
var checked = function (itemValue, valueObj,rangeIdKey) {
if (valueObj == null) {
return false;
}
if(rangeIdKey){
if (valueObj[rangeIdKey] == itemValue) {
return true;
}
}else{
if (valueObj == itemValue) {
return true;
}
}
return false;
}
module.exports = {
checked: checked
}
</wxs>
<view class="items">
<radio-group bindchange="_change">
<label class="item" wx:for="{
{datas}}" wx:key="{
{item}}">
<block wx:if="{
{rangeKey}}">
<radio disabled="{
{disabled}}" value="{
{item[rangeIdKey]}}" checked="{
{utils.checked(item[rangeIdKey],valueObj,rangeIdKey)}}" />
<text>{
{item[rangeKey]}}</text>
</block>
<block wx:else>
<radio disabled="{
{disabled}}" value="{
{item}}" checked="{
{utils.checked(item,valueObj,null)}}" />
<text>{
{item}}</text>
</block>
</label>
</radio-group>
</view>
2.js代码
扫描二维码关注公众号,回复:
14969028 查看本文章
<wxs module="utils">
/**
*检测itemValue数据是否在valueIndex中选中
*/
var checked = function (itemValue, valueObj,rangeIdKey) {
if (valueObj == null) {
return false;
}
if(rangeIdKey){
if (valueObj[rangeIdKey] == itemValue) {
return true;
}
}else{
if (valueObj == itemValue) {
return true;
}
}
return false;
}
module.exports = {
checked: checked
}
</wxs>
<view class="items">
<radio-group bindchange="_change">
<label class="item" wx:for="{
{datas}}" wx:key="{
{item}}">
<block wx:if="{
{rangeKey}}">
<radio disabled="{
{disabled}}" value="{
{item[rangeIdKey]}}" checked="{
{utils.checked(item[rangeIdKey],valueObj,rangeIdKey)}}" />
<text>{
{
item[rangeKey]}}</text>
</block>
<block wx:else>
<radio disabled="{
{disabled}}" value="{
{item}}" checked="{
{utils.checked(item,valueObj,null)}}" />
<text>{
{
item}}</text>
</block>
</label>
</radio-group>
</view>
3.css代码
.items{
height: auto;
}
.item{
margin-right: 10px;
display: inline-block;
}
七、使用说明
1.html代码
<view class="page">
<view class="title">1. 基础实例</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">本地数据(字符):</text>
<view class="flex-item">
<smart-radio id="demo1" model:value="{
{ value1 }}" datas="{
{values1}}" bindchange="change1"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value1}}</view>
</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">本地数据(对象):</text>
<view class="flex-item">
<smart-radio id="demo2" model:value="{
{ value2 }}" datas="{
{values2}}" rangeKey="label" rangeIdKey="id" bindchange="change2"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value2}}</view>
</view>
<view class="title">2. 远程数据</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">远程数据(字符):</text>
<view class="flex-item">
<smart-radio id="demo1" remote="{
{true}}" model:value="{
{ value21 }}" url="{
{url21}}" method="get" bindchange="change1"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value21}}</view>
</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">远程数据(对象):</text>
<view class="flex-item">
<smart-radio id="demo2" remote="{
{true}}" model:value="{
{ value22 }}" url="{
{url22}}" method="get" rangeKey="name" rangeIdKey="id" bindchange="change22"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value22}}</view>
</view>
<view class="title">3. 其它逻辑</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">禁用选择:</text>
<view class="flex-item">
<smart-radio id="demo31" model:value="{
{ value31 }}" datas="{
{values31}}" disabled="{
{true}}" bindchange="change31"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value1}}</view>
</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">事件监听:</text>
<view class="flex-item">
<smart-radio id="demo32" model:value="{
{ value32 }}" datas="{
{values32}}" bindchange="change32"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value1}}</view>
</view>
<view class="demo-item">
<view class="flex form-item">
<text class="label">方法调用:</text>
<view class="flex-item">
<smart-radio id="demo33" remote="{
{true}}" model:value="{
{ value33 }}" url="{
{url33}}" extraPama="{
{extraPama}}" pamaCreator="{
{pamaCreator}}" rangeKey="name" rangeIdKey="id" method="post" bindchange="change33" bindloadEnd="loadEnd"></smart-radio>
</view>
</view>
<view>当前选中的结果:{
{value33}}</view>
</view>
<button style="margin-top: 10px;" bindtap="loadData">加载数据</button>
<button style="margin-top: 10px;" bindtap="setValue">设置选中</button>
<button style="margin-top: 10px;" bindtap="getValue">获取选中</button>
</view>
2.js代码
Page({
/**
* 页面的初始数据
*/
data: {
value1: '美国',
values1: ['美国', '中国', '巴西', '日本'],
value2: JSON.stringify({
id: 3,
label: '选项三'
}),
values2: [{
id: 1,
label: '选项一'
}, {
id: 2,
label: '选项二'
}, {
id: 3,
label: '选项三'
}, {
id: 4,
label: '选项四'
}, {
id: 5,
label: '选项5'
}, {
id: 6,
label: '选项6'
}, {
id: 7,
label: '选项7'
}],
value21: '选项2',
url21:"http://127.0.0.1:3000/api/listStringData",
value22: JSON.stringify({
id: 2,
label: '选项2'
}),
url22:"http://127.0.0.1:3000/api/listObjData",
value31: '美国',
values31: ['美国', '中国', '巴西', '日本'],
url33:"http://127.0.0.1:3000/api/listSearchData",
value33: JSON.stringify({
id: 2,
name: '选项2'
}),
extraPama:{
name:'1'
},
pamaCreator:function(pama){
if(!pama){
pama = {
};
}
pama.age = 111;
return pama;
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
},
change33(e){
console.log(e);
},
loadEnd(e){
console.log(e);
},
loadData(e){
this.selectComponent("#demo33").loadData();
},
setValue(e){
this.selectComponent("#demo33").setValue(JSON.stringify({
id:10,
name:'选项11'
}));
},
getValue(e){
console.log(this.selectComponent("#demo33").getValue());
},
})
3.css代码
.page {
padding: 10px
}
.title {
height: 30px;
line-height: 30px;
font-weight: bold;
}
.flex {
display: flex;
}
.flex-item {
flex: 1;
}
.form-item {
min-height: 30px;
font-size: 14px;
line-height: 30px;
}
.form-item .label {
width: 140px;
color: #555
}
.demo-item {
border-bottom: 10px solid #f8f8f8;
margin-bottom: 10px;
padding-bottom: 10px;
}