当前位置:   article > 正文

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

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

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

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

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

一、计数器组件定义

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

index.wxml代码如下:

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

index.wxss代码如下:

  1. /* components/Counter/index.wxss */
  2. .counter-wrap{ white-space: nowrap; }
  3. .counter-wrap .btn, .counter-wrap .number{
  4. height: 60rpx;
  5. line-height: 60rpx;
  6. padding: 0;
  7. display: inline-block;
  8. vertical-align: middle;
  9. text-align: center;
  10. }
  11. .counter-wrap .btn{
  12. width: 60rpx;
  13. line-height: 50rpx;
  14. font-size: 50rpx;
  15. color: #000000;
  16. border: 1px solid #cccccc;
  17. border-radius: 8rpx;
  18. background-color: transparent;
  19. padding: 0;
  20. }
  21. .counter-wrap .btn:disabled{ opacity: .6; }
  22. .counter-wrap .number{ width: 80rpx; }
  1. // components/Counter/index.js
  2. Component({
  3. /**
  4. * 组件的属性列表
  5. */
  6. properties: {
  7. // 值
  8. value: {
  9. type: Number,
  10. value: 0
  11. },
  12. // 最小值
  13. min: {
  14. type: Number,
  15. value: null
  16. },
  17. // 最大值
  18. max: {
  19. type: Number,
  20. value: null
  21. }
  22. },
  23. /**
  24. * 组件的初始数据
  25. */
  26. data: {
  27. isDisabledAdd: false, // 是否禁用 加 按钮
  28. isDisabledMul: false // 是否禁用 减 按钮
  29. },
  30. /**
  31. * 组件的方法列表
  32. */
  33. methods: {
  34. // 通知父组件值改变
  35. triggerMsg(value){
  36. this.triggerEvent('valueChange', {value});
  37. },
  38. // 递增事件
  39. addEvent(){
  40. const value = this.data.value + 1;
  41. // 通知父组件 更新数据
  42. this.triggerMsg(value);
  43. },
  44. // 递减事件
  45. mulEvent(){
  46. const value = this.data.value - 1;
  47. // 通知父组件 更新数据
  48. this.triggerMsg(value);
  49. }
  50. }
  51. })

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

二、全局组件定义

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

  1. {
  2. "pages": [
  3. "pages/index/index",
  4. "pages/logs/logs",
  5. "pages/mine/index"
  6. ],
  7. "window": {
  8. "navigationBarTextStyle": "black",
  9. "navigationBarTitleText": "Weixin",
  10. "navigationBarBackgroundColor": "#ffffff",
  11. "navigationStyle": "custom"
  12. },
  13. "usingComponents": {
  14. "custom-header": "./components/Header/index",
  15. "custom-counter": "./components/Counter/index"
  16. }
  17. }

三、计数器组件的引用

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

index.wxml代码如下:

  1. <!--pages/index/index.wxml-->
  2. <Header title="首页"></Header>
  3. <view style="padding: 30rpx;">
  4. <view class="table">
  5. <view class="row">
  6. <view class="cell">
  7. <custom-counter value="{{value1}}" bind:valueChange="valueChangeEvent"></custom-counter>
  8. </view>
  9. <view class="cell">
  10. <custom-counter value="{{value2}}" max="8" bind:valueChange="valueChangeEvent"></custom-counter>
  11. </view>
  12. </view>
  13. <view class="row">
  14. <view class="cell">
  15. <custom-counter value="{{value3}}" min="2" bind:valueChange="valueChangeEvent"></custom-counter>
  16. </view>
  17. <view class="cell">
  18. <custom-counter value="{{value4}}" min="0" max="10" bind:valueChange="valueChangeEvent"></custom-counter>
  19. </view>
  20. </view>
  21. </view>
  22. </view>

index.js代码如下:

  1. // pages/index/index.js
  2. Page({
  3. /**
  4. * 页面的初始数据
  5. */
  6. data: {
  7. value1: 0,
  8. value2: 0,
  9. value3: 0,
  10. value4: 0
  11. },
  12. valueChangeEvent(e){
  13. console.log(e);
  14. }
  15. })

        页面效果如下图:

四、双向绑定数值

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

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

  1. <!--pages/index/index.wxml-->
  2. <Header title="首页"></Header>
  3. <view style="padding: 30rpx;">
  4. <view class="table">
  5. <view class="row">
  6. <view class="cell">
  7. <custom-counter value="{{value1}}" target="value1" bind:valueChange="valueChangeEvent"></custom-counter>
  8. </view>
  9. <view class="cell">
  10. <custom-counter value="{{value2}}" target="value2" max="8" bind:valueChange="valueChangeEvent"></custom-counter>
  11. </view>
  12. </view>
  13. <view class="row">
  14. <view class="cell">
  15. <custom-counter value="{{value3}}" target="value3" min="2" bind:valueChange="valueChangeEvent"></custom-counter>
  16. </view>
  17. <view class="cell">
  18. <custom-counter value="{{value4}}" target="value4" min="0" max="10" bind:valueChange="valueChangeEvent"></custom-counter>
  19. </view>
  20. </view>
  21. </view>
  22. </view>

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

  1. // components/Counter/index.js
  2. Component({
  3. /**
  4. * 组件的属性列表
  5. */
  6. properties: {
  7. // 值
  8. value: {
  9. type: Number,
  10. value: 0
  11. },
  12. // 目标key
  13. target: {
  14. type: String,
  15. value: ''
  16. },
  17. // 最小值
  18. min: {
  19. type: Number,
  20. value: null
  21. },
  22. // 最大值
  23. max: {
  24. type: Number,
  25. value: null
  26. }
  27. },
  28. /**
  29. * 组件的初始数据
  30. */
  31. data: {
  32. isDisabledAdd: false, // 是否禁用 加 按钮
  33. isDisabledMul: false // 是否禁用 减 按钮
  34. },
  35. /**
  36. * 组件的方法列表
  37. */
  38. methods: {
  39. // 通知父组件值改变
  40. triggerMsg(value){
  41. const data = {};
  42. if(!this.data.target) data['value'] = value;
  43. else data[this.data.target] = value;
  44. this.triggerEvent('valueChange', data);
  45. },
  46. // 递增事件
  47. addEvent(){
  48. const value = this.data.value + 1;
  49. // 通知父组件 更新数据
  50. this.triggerMsg(value);
  51. },
  52. // 递减事件
  53. mulEvent(){
  54. const value = this.data.value - 1;
  55. // 通知父组件 更新数据
  56. this.triggerMsg(value);
  57. }
  58. }
  59. })

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

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

  1. // pages/index/index.js
  2. Page({
  3. /**
  4. * 页面的初始数据
  5. */
  6. data: {
  7. value1: 0,
  8. value2: 0,
  9. value3: 0,
  10. value4: 0
  11. },
  12. valueChangeEvent(e){
  13. this.setData(e.detail);
  14. }
  15. })

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

五、限定大小值

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

Counter组件index.js代码如下:

  1. // components/Counter/index.js
  2. Component({
  3. /**
  4. * 组件的属性列表
  5. */
  6. properties: {
  7. // 值
  8. value: {
  9. type: Number,
  10. value: 0
  11. },
  12. // 目标key
  13. target: {
  14. type: String,
  15. value: ''
  16. },
  17. // 最小值
  18. min: {
  19. type: Number,
  20. value: null
  21. },
  22. // 最大值
  23. max: {
  24. type: Number,
  25. value: null
  26. }
  27. },
  28. /**
  29. * 组件的初始数据
  30. */
  31. data: {
  32. isDisabledAdd: false, // 是否禁用 加 按钮
  33. isDisabledMul: false // 是否禁用 减 按钮
  34. },
  35. /**
  36. * 组件的方法列表
  37. */
  38. methods: {
  39. // 通知父组件值改变
  40. triggerMsg(value){
  41. const data = {};
  42. if(!this.data.target) data['value'] = value;
  43. else data[this.data.target] = value;
  44. this.triggerEvent('valueChange', data);
  45. },
  46. // 递增事件
  47. addEvent(){
  48. const value = this.data.value + 1;
  49. // 最大值不为空时,判断最大值
  50. if(this.data.max != null && this.data.max < value) {
  51. return;
  52. }
  53. // 通知父组件 更新数据
  54. this.triggerMsg(value);
  55. },
  56. // 递减事件
  57. mulEvent(){
  58. const value = this.data.value - 1;
  59. // 最小值不为空时,判断最小值
  60. if(this.data.min != null && this.data.min > value) {
  61. return;
  62. }
  63. // 通知父组件 更新数据
  64. this.triggerMsg(value);
  65. }
  66. }
  67. })

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

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

六、禁用按钮

        

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

  1. // components/Counter/index.js
  2. Component({
  3. /**
  4. * 组件的属性列表
  5. */
  6. properties: {
  7. // 值
  8. value: {
  9. type: Number,
  10. value: 0
  11. },
  12. // 目标key
  13. target: {
  14. type: String,
  15. value: ''
  16. },
  17. // 最小值
  18. min: {
  19. type: Number,
  20. value: null
  21. },
  22. // 最大值
  23. max: {
  24. type: Number,
  25. value: null
  26. }
  27. },
  28. /**
  29. * 组件的初始数据
  30. */
  31. data: {
  32. isDisabledAdd: false, // 是否禁用 加 按钮
  33. isDisabledMul: false // 是否禁用 减 按钮
  34. },
  35. /**
  36. * 组件的方法列表
  37. */
  38. methods: {
  39. // 通知父组件值改变
  40. triggerMsg(value){
  41. const data = {};
  42. if(!this.data.target) data['value'] = value;
  43. else data[this.data.target] = value;
  44. this.triggerEvent('valueChange', data);
  45. },
  46. // 递增事件
  47. addEvent(){
  48. const value = this.data.value + 1;
  49. // 最大值不为空时,判断最大值
  50. if(this.data.max != null && this.data.max < value) {
  51. this.setData({ isDisabledAdd: true }); // 当超过最大值时,禁用 加 按钮
  52. return;
  53. }
  54. // 未超最大值时,如果 加 按钮为true, 置为false可用状态
  55. else if(this.data.isDisabledAdd) {
  56. this.setData({ isDisabledAdd: false })
  57. }
  58. // 当 加 按钮可用时,如 减 按钮为禁用状态,解除禁用
  59. if(this.data.isDisabledMul) this.setData({isDisabledMul: false});
  60. // 通知父组件 更新数据
  61. this.triggerMsg(value);
  62. },
  63. // 递减事件
  64. mulEvent(){
  65. const value = this.data.value - 1;
  66. // 最小值不为空时,判断最小值
  67. if(this.data.min != null && this.data.min > value) {
  68. this.setData({ isDisabledMul: true }); // 当底于最小值时,禁用 减 按钮
  69. return;
  70. }
  71. // 未低于小最值时,如果 减 按钮为true,置为false可用状态
  72. else if(this.data.isDisabledMul) {
  73. this.setData({ isDisabledMul: false })
  74. }
  75. // 当 减 按钮可用时,如 加按钮为禁用状态,解除禁用
  76. if(this.data.isDisabledAdd) this.setData({isDisabledAdd: false});
  77. // 通知父组件 更新数据
  78. this.triggerMsg(value);
  79. }
  80. }
  81. })

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/933666
推荐阅读
相关标签
  

闽ICP备14008679号