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

news2024/11/15 20:44:04

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

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

  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
    },
    // 目标key
    target: {
      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
    },
    // 目标key
    target: {
      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
    },
    // 目标key
    target: {
      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);
    }
  }
})

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1970722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP教育培训小程序系统源码

&#x1f680;【学习新纪元】解锁教育培训小程序的无限可能✨ &#x1f4da; 引言&#xff1a;教育培训新风尚&#xff0c;小程序来引领&#xff01; Hey小伙伴们&#xff0c;是不是还在为找不到合适的学习资源而烦恼&#xff1f;或是厌倦了传统教育模式的单调&#xff1f;今…

Monaco 使用 SignatureHelpProvider

Monaco 中 SignatureHelpProvider 是方法提示说明&#xff0c;当敲入方法名时&#xff0c;系统会提示方法名称和对应的参数信息。效果如下&#xff1a; 通过 registerSignatureHelpProvider 实现 SignatureHelpProvider 处理函数。 实现 signatureHelpTriggerCharacters 和 pro…

我们如何优化 Elasticsearch Serverless 中的刷新成本

作者&#xff1a;来自 Elastic Francisco Fernndez Castao, Henning Andersen 最近&#xff0c;我们推出了 Elastic Cloud Serverless 产品&#xff0c;旨在提供在云中运行搜索工作负载的无缝体验。为了推出该产品&#xff0c;我们重新设计了 Elasticsearch&#xff0c;将存储与…

深入了解下 Markdown 的原理

前面讲了 Markdown 的基本语法&#xff0c;常见的 Markdown 编辑器&#xff0c;在继续讲解其他知识之前&#xff0c;有必要稍微深入了解一下 Markdown 与 HTML 的关系。 ‍ ‍ HTML 简介 什么是 HTML&#xff1f;其实它也是标记语言的一种&#xff0c;但是比 Markdown 更重…

Java面试题--JVM大厂篇之深入分析Parallel GC:从原理到优化

目录 引言: 正文&#xff1a; 1. Parallel GC原理解析 2. Parallel GC关键参数配置 3. 常见调优场景与技巧 4. 监控与日志分析 结束语&#xff1a; 引言: 在Java应用程序中&#xff0c;垃圾回收&#xff08;Garbage Collection, GC&#xff09;扮演着至关重要的角色。对…

【学术会议征稿】第三届图像处理、计算机视觉与机器学习国际学术会议(ICICML 2024)

第三届图像处理、计算机视觉与机器学习国际学术会议(ICICML 2024) 2024 3rd International Conference on Image Processing, Computer Vision and Machine Learning 重要信息 大会官网&#xff1a;参会投稿/了解会议详情 大会时间&#xff1a;2024年11月22日-24日 大会地…

大米cms支付逻辑漏洞

1.打开环境 注册账户 随机选择一个产品 修改数据

什么是折叠幼儿床?该如何认证?

​折叠幼儿床具有如下特征&#xff1a; 轻巧便携 用于睡眠的幼儿床&#xff0c;不使用时会折叠 有幼儿护栏&#xff0c;且必须带底板&#xff08;不包括没有地板的婴儿围栏&#xff09; 图片 亚马逊政策规定&#xff0c;通过亚马逊网站销售的折叠幼儿床必须符合特定标准的测…

视频转文字在线提取怎么弄?5款软件帮你解决

三伏天炎炎&#xff0c;阳光炽热&#xff0c;视频内容分享正当时。然而&#xff0c;在海量视频信息中快速提取关键信息却成了难题。试想&#xff0c;如果能一键将视频中的精彩讲解或会议要点转换成文字&#xff0c;岂不省时又高效&#xff1f; 那么问题来了&#xff0c;面对市…

项目实战--不推荐使用@Autowired实现注入

不推荐使用Autowired实现字段注入 一、前言二、字段注入2.1 字段注入的使用2.2 字段注入的弊端2.2.1 与Spring的IOC机制紧密耦合2.2.2 无法使用final修饰符2.2.3 隐藏依赖性2.2.4 无法对注入的属性进行安全检查2.2.5 掩饰单一职责的设计思想 三、设值注入四、构造器注入五、总结…

前端面试:项目细节重难点问题分享(十五)

更多详情&#xff1a;爱米的前端小笔记&#xff08;csdn~xitujuejin~zhiHu~Baidu~小红shu&#xff09;同步更新&#xff0c;等你来看&#xff01;都是利用下班时间整理的&#xff0c;整理不易&#xff0c;大家多多&#x1f44d;&#x1f49b;➕&#x1f914;哦&#xff01;你们…

ComfyUI 实战教程:图片添加文字

大家好&#xff0c;我是每天分享AI应用的萤火君&#xff01; 在AI绘画中书写文字一直是个老大难的问题&#xff0c;直到SDXL的出现&#xff0c;文字生成才迎来转机&#xff0c;可以在提示词中指定一些英文字符&#xff0c;不过也是经常出错&#xff0c;生成中文就更加不可求了…

uView input输入框和search输入框实现搜索功能

背景&#xff1a; 在手机端实现搜索框的“查询功能”&#xff0c;使用uView组件库。有两种实现思路&#xff1a; 1.input输入框 2.search搜索框 效果展示&#xff1a; 一、search搜索框 官方文档&#xff1a;点击跳转uView官网 实际代码&#xff1a; //u-search组件 <u-se…

人生五大成熟表现

三十而立&#xff1b;立什么&#xff1f;立身、立业、立家&#xff1b; 四十不惑&#xff1b;明白了什么&#xff1f;明白了社会&#xff0c;责任、自己&#xff1b; 五十知天命&#xff1b;知道了什么&#xff1f;知道了命运轨迹&#xff0c;人生定位&#xff1b; 六十而顺&am…

58 简单学生管理系统【项目需求、数据库搭建、项目搭建、功能实现(注册功能、登录功能完善验证码功能(Session-会话对象))】

简单学生管理系统 项目需求 数据库搭建 数据库建表 导数据库sql 了解 项目搭建 导包&#xff0c;基础页面&#xff0c;实体类&#xff0c;工具类 基础页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><ti…

深入实践,浅谈EHS管理的智能化转型

随着人工智能、大数据、云计算等先进技术的飞速发展&#xff0c;EHS管理体系与管理软件的融合正步入一个全新的智能化时代。这一转型不仅进一步提升了EHS管理的效率和精准度&#xff0c;还为企业带来了前所未有的管理视野和决策支持。 一、创新驱动&#xff0c;深化EHS管理的智…

深入探讨Google谷歌助力孟加拉slots游戏广告市场前景

深入探讨Google谷歌助力孟加拉slots游戏广告市场前景 在深入探讨孟加拉游戏广告投放于Google谷歌平台的优势时&#xff0c;不得不提及其强大的数据分析与精准定位能力。谷歌广告平台拥有全球领先的数据处理技术&#xff0c;能够基于用户的搜索历史、浏览行为、地理位置等多维度…

C语言程序设计24

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.1 求下列算数表达式的值 &#xff08;1&#xff09;xa%3*(int)(xy)%2/4 设x2.5,a7,y4.7 (2)(float)(ab)/2(int)x%(int)y 设 a2,b3,x3.5,y2.5 代码&#xff08;1&#xff09;&#xff1a;…

贪心系列专题篇三

目录 单调递增的数字 坏了的计算器 合并区间 无重叠区间 用最少数量的箭 声明&#xff1a;接下来主要使用贪心法来解决问题&#xff01;&#xff01;&#xff01; 单调递增的数字 题目 思路 如果我们遍历整个数组&#xff0c;然后对每个数k从[k,0]依次遍历寻找“单调递…

人力资源专家推荐:2024年十大HR软件

本篇文章介绍了以下人力资源管理工具&#xff1a;Moka、北森云计算、友人才、人瑞人才、Zoho People、金蝶之家、Gusto、Workday HCM、Namely、UKG Pro。 在选择合适的人力资源软件时&#xff0c;许多企业常常面临各种挑战&#xff0c;例如如何确保软件功能全面、用户体验良好&…