当前位置: 首页 > news >正文

微信小程序 - 自定义计数器

       微信小程序通过自定义组件,实现计数器值的增加、减少、清零、最大最小值限定、禁用等操作。通过按钮事件触发方式,更新计数器的值,并修改相关联的其它变量。通过提升用户体验,对计数器进行优化设计,使用户操作更加便捷和直观。

        计数器的实现主要涉及到几个关键部分:

  1. 计数值的增加:通过按钮事件触发方式,实现计数器值的增加,当触增加操作时,更新相应的计数值、按钮状态等。
  2. 计数值的减少:通过按钮事件触发方式,实现计数器值的减少。当触减少操作时,更新相应的计数值、按钮状态等。
  3. 计数值的清零:通过按钮事件等触发方式,相关业务变量变更、逻辑调整等,实现计数值的清零。
  4. 大小值限定:通过按钮事件等触发方式,根据组件定义时指定的最大值、最小值限定增、减数值的范围。
  5. 计数器按钮的禁用:通过按钮事件等触发方式,相关业务变量变更、逻辑调整等,实现计数器按钮的禁用。

一、计数器组件定义

        首先在项目中创建计数器组件(Counter),如下图:

index.wxml代码如下:

<!--components/Counter/index.wxml-->
<view class="counter-wrap"><button class="btn mul" disabled="{{isDisabledMul}}" bind:tap="mulEvent">-</button><input type="number" value="{{value}}" class="number" /><button class="btn add" disabled="{{isDisabledAdd}}" bind:tap="addEvent">+</button>
</view>

index.wxss代码如下:

/* components/Counter/index.wxss */
.counter-wrap{ white-space: nowrap; }
.counter-wrap .btn, .counter-wrap .number{ height: 60rpx; line-height: 60rpx; padding: 0; display: inline-block; vertical-align: middle; text-align: center; 
}
.counter-wrap .btn{ width: 60rpx; line-height: 50rpx; font-size: 50rpx; color: #000000; border: 1px solid #cccccc; border-radius: 8rpx; background-color: transparent; padding: 0; 
}
.counter-wrap .btn:disabled{ opacity: .6; }
.counter-wrap .number{ width: 80rpx; }
// components/Counter/index.js
Component({/*** 组件的属性列表*/properties: {// 值value: {type: Number,value: 0},// 最小值min: {type: Number,value: null},// 最大值max: {type: Number,value: null}},/*** 组件的初始数据*/data: {isDisabledAdd: false,     // 是否禁用 加 按钮isDisabledMul: false      // 是否禁用 减 按钮},/*** 组件的方法列表*/methods: {// 通知父组件值改变triggerMsg(value){this.triggerEvent('valueChange', {value});},// 递增事件addEvent(){const value = this.data.value + 1;// 通知父组件 更新数据this.triggerMsg(value);},// 递减事件mulEvent(){const value = this.data.value - 1;// 通知父组件 更新数据this.triggerMsg(value);}}
})

        自定义组件触发事件时,需要使用 triggerEvent 方法,指定事件名、detail对象和事件选项,通知父组件并将相关数据发送给父组件。

二、全局组件定义

        在 app.json 中声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。则在app.json中,增加计数器组件,将其定义为全局组件。代码如下:

{"pages": ["pages/index/index","pages/logs/logs","pages/mine/index"],"window": {"navigationBarTextStyle": "black","navigationBarTitleText": "Weixin","navigationBarBackgroundColor": "#ffffff","navigationStyle": "custom"},"usingComponents": {"custom-header": "./components/Header/index","custom-counter": "./components/Counter/index"}
}

三、计数器组件的引用

        由于计数器组件已定义为全局组件,所以在小程序首页中,直接使用即可。代码如下:

index.wxml代码如下:

<!--pages/index/index.wxml-->
<Header title="首页"></Header>
<view style="padding: 30rpx;"><view class="table"><view class="row"><view class="cell"><custom-counter value="{{value1}}" bind:valueChange="valueChangeEvent"></custom-counter></view><view class="cell"><custom-counter value="{{value2}}" max="8" bind:valueChange="valueChangeEvent"></custom-counter></view></view><view class="row"><view class="cell"><custom-counter value="{{value3}}" min="2" bind:valueChange="valueChangeEvent"></custom-counter></view><view class="cell"><custom-counter value="{{value4}}" min="0" max="10" bind:valueChange="valueChangeEvent"></custom-counter></view></view></view>
</view>

index.js代码如下:

// pages/index/index.js
Page({/*** 页面的初始数据*/data: {value1: 0,value2: 0,value3: 0,value4: 0},valueChangeEvent(e){console.log(e);}
})

        页面效果如下图:

四、双向绑定数值

        如上图可见,此时计数器已可正常通信了,但是首页中定义了四个计数器,对应变量分别为value1、value2、value3、value4;但是小程序中没有双向绑定功能,所以这里需要在定义计数器组件时,告诉子组件将变化的值,绑定给谁。

        在首页定义组件时,增加target属性,告知子组件,首页index.wxml代码如下:

<!--pages/index/index.wxml-->
<Header title="首页"></Header>
<view style="padding: 30rpx;"><view class="table"><view class="row"><view class="cell"><custom-counter value="{{value1}}" target="value1" bind:valueChange="valueChangeEvent"></custom-counter></view><view class="cell"><custom-counter value="{{value2}}" target="value2" max="8" bind:valueChange="valueChangeEvent"></custom-counter></view></view><view class="row"><view class="cell"><custom-counter value="{{value3}}" target="value3" min="2" bind:valueChange="valueChangeEvent"></custom-counter></view><view class="cell"><custom-counter value="{{value4}}" target="value4" min="0" max="10" bind:valueChange="valueChangeEvent"></custom-counter></view></view></view>
</view>

        然后再将Counter计数器组件中,将index.js中的函数triggerMsg()稍作修改,代码如下:

// components/Counter/index.js
Component({/*** 组件的属性列表*/properties: {// 值value: {type: Number,value: 0},// 目标keytarget: {type: String,value: ''},// 最小值min: {type: Number,value: null},// 最大值max: {type: Number,value: null}},/*** 组件的初始数据*/data: {isDisabledAdd: false,     // 是否禁用 加 按钮isDisabledMul: false      // 是否禁用 减 按钮},/*** 组件的方法列表*/methods: {// 通知父组件值改变triggerMsg(value){const data = {};if(!this.data.target) data['value'] = value;else data[this.data.target] = value;this.triggerEvent('valueChange', data);},// 递增事件addEvent(){const value = this.data.value + 1;// 通知父组件 更新数据this.triggerMsg(value);},// 递减事件mulEvent(){const value = this.data.value - 1;// 通知父组件 更新数据this.triggerMsg(value);}}
})

        此时触发首页计数器增、减按钮,返回的数据如下:

        由此可见,当首页中valueChangeEvent()函数触发后,直接将e.detail塞给this.setData()函数即可。代码如下:

// pages/index/index.js
Page({/*** 页面的初始数据*/data: {value1: 0,value2: 0,value3: 0,value4: 0},valueChangeEvent(e){this.setData(e.detail);}
})

        现在不同计数器触发增、减按钮事件后,只会修改当前计数器的值了,如下图:

五、限定大小值

        判断最大值和最小值限定前,先判断当前计数器组件是否设置了最大值和最小值。当max或min变量值不为null时,表明当前组件已设置了最大值和最小值,代码如下:

Counter组件index.js代码如下:

// components/Counter/index.js
Component({/*** 组件的属性列表*/properties: {// 值value: {type: Number,value: 0},// 目标keytarget: {type: String,value: ''},// 最小值min: {type: Number,value: null},// 最大值max: {type: Number,value: null}},/*** 组件的初始数据*/data: {isDisabledAdd: false,     // 是否禁用 加 按钮isDisabledMul: false      // 是否禁用 减 按钮},/*** 组件的方法列表*/methods: {// 通知父组件值改变triggerMsg(value){const data = {};if(!this.data.target) data['value'] = value;else data[this.data.target] = value;this.triggerEvent('valueChange', data);},// 递增事件addEvent(){const value = this.data.value + 1;// 最大值不为空时,判断最大值if(this.data.max != null && this.data.max < value)  {return;} // 通知父组件 更新数据this.triggerMsg(value);},// 递减事件mulEvent(){const value = this.data.value - 1;// 最小值不为空时,判断最小值if(this.data.min != null && this.data.min > value) {return;} // 通知父组件 更新数据this.triggerMsg(value);}}
})

        限定大小值范围条件判断:

  1. 当最大值不为null时,并且当前数值大于最大值时,返回return禁止通知父组件修改值。
  2. 当最小值不为null时,并且当前数值小于最小值时,返回return禁止通知父组件修改值。

六、禁用按钮

        

        如上图,最大值和最小值限定后,当当前计数器值为最大值或最小值时,将增加按钮或减少按钮,置灰为不可用状态。代码如下:

// components/Counter/index.js
Component({/*** 组件的属性列表*/properties: {// 值value: {type: Number,value: 0},// 目标keytarget: {type: String,value: ''},// 最小值min: {type: Number,value: null},// 最大值max: {type: Number,value: null}},/*** 组件的初始数据*/data: {isDisabledAdd: false,     // 是否禁用 加 按钮isDisabledMul: false      // 是否禁用 减 按钮},/*** 组件的方法列表*/methods: {// 通知父组件值改变triggerMsg(value){const data = {};if(!this.data.target) data['value'] = value;else data[this.data.target] = value;this.triggerEvent('valueChange', data);},// 递增事件addEvent(){const value = this.data.value + 1;// 最大值不为空时,判断最大值if(this.data.max != null && this.data.max < value)  {this.setData({ isDisabledAdd: true });            // 当超过最大值时,禁用 加 按钮 return;} // 未超最大值时,如果 加 按钮为true, 置为false可用状态else if(this.data.isDisabledAdd) {this.setData({ isDisabledAdd: false })  }// 当 加 按钮可用时,如 减 按钮为禁用状态,解除禁用if(this.data.isDisabledMul) this.setData({isDisabledMul: false});// 通知父组件 更新数据this.triggerMsg(value);},// 递减事件mulEvent(){const value = this.data.value - 1;// 最小值不为空时,判断最小值if(this.data.min != null && this.data.min > value) {this.setData({ isDisabledMul: true });            // 当底于最小值时,禁用 减 按钮return;} // 未低于小最值时,如果 减 按钮为true,置为false可用状态else if(this.data.isDisabledMul) {this.setData({ isDisabledMul: false })}// 当 减 按钮可用时,如 加按钮为禁用状态,解除禁用if(this.data.isDisabledAdd) this.setData({isDisabledAdd: false});// 通知父组件 更新数据this.triggerMsg(value);}}
})

        具体逻辑代码中已具体说明,这里就不再细说了。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Oracle11g RAC-更换存储
  • 63、ELK安装和部署
  • 情感推理在医疗领域的应用
  • 动态规划之多状态 dp 问题
  • 十三、Kafka(系列)-Kafka入门(重试机制)
  • springboot系列教程(三十一):springboot整合Nacos组件,环境搭建和入门案例详解
  • 【Qt】为什么Qt是你选择的理由?
  • Android渠道配置不同依赖性
  • 小程序商品图片有什么要求
  • 使用 OpenCV 进行轮廓处理和图像保存
  • flink 1.17 测试
  • VSCode上安装C#环境教程
  • springboot+vue+mybatis音乐网站的设计+PPT+论文+讲解+售后
  • kafka cmd
  • 酸性蓄电池的结构与工作原理是什么?
  • Angular 2 DI - IoC DI - 1
  • ES学习笔记(12)--Symbol
  • exports和module.exports
  • JavaScript实现分页效果
  • javascript数组去重/查找/插入/删除
  • Java超时控制的实现
  • JS 面试题总结
  • js递归,无限分级树形折叠菜单
  • MySQL用户中的%到底包不包括localhost?
  • Rancher-k8s加速安装文档
  • Service Worker
  • 动态魔术使用DBMS_SQL
  • 读懂package.json -- 依赖管理
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 码农张的Bug人生 - 初来乍到
  • 扑朔迷离的属性和特性【彻底弄清】
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 深入 Nginx 之配置篇
  • 找一份好的前端工作,起点很重要
  • ​MySQL主从复制一致性检测
  • ​批处理文件中的errorlevel用法
  • #{}和${}的区别是什么 -- java面试
  • ( 10 )MySQL中的外键
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (2020)Java后端开发----(面试题和笔试题)
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (poj1.3.2)1791(构造法模拟)
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (二)Linux——Linux常用指令
  • (翻译)terry crowley: 写给程序员
  • (九)信息融合方式简介
  • (南京观海微电子)——COF介绍
  • (三)uboot源码分析
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • ./configure、make、make install 命令
  • .NET 8.0 中有哪些新的变化?
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法