微信小程序 - 自定义计数器 - 优化(键盘输入校验)

news2024/11/15 9:16:15

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

        计数器的实现主要涉及到几个关键部分,上一篇已重点讲过,该篇将讲述一下中间input输入框值变化后的校验操作。

        由于该篇是接上一篇继续完善和优化,所以建议先了解上一篇后,再来看此篇内容。地址:微信小程序 - 自定义计数器-CSDN博客

        如上图中,增加、减小按钮操作已限定了其值范围;但是通过小键盘输入内容后,发现值并不正规或者已超出了其限定范围,所以需要增加监听input输入框的内容变化,对其值进行校验和处理。

一、bindinput事件监听

        首页需要在Counter计数器中绑定监听事件,bindinput事件会在每次输入一个数字、字母或符号时执行一次。index.wxml代码如下:

<view class="counter-wrap">
  <button class="btn mul" disabled="{{isDisabledMul}}" bind:tap="mulEvent">-</button>
  <input type="number" value="{{value}}" class="number" bindinput="inputEvent" />
  <button class="btn add" disabled="{{isDisabledAdd}}" bind:tap="addEvent">+</button>
</view>

        index.js中添加inputEvent监听事件,代码如下:

// 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: {
    // 略...    

    // 输入后 监听事件
    inputEvent(e){
      console.log(e.detail.value);
    }
  }
})

        如代码所示,inputEvent监听事件中,是通过e.detail.value获取修改后的新内容。

二、防抖操作

        每输入一个数字,inputEvent函数则会被执行一次,此时用户内容可能并没有输入完整,所以这里增加一个计时器,当用户最后一次输入内容,再执行数值校验。代码如下:

// 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: {
    // 略...

    // 输入后  监听事件
    inputEvent(e){
      clearTimeout(this.inputHandle);
      // 开始计时
      this.inputHandle = setTimeout((value) => {
        
      }, 800);
    }
  }
})

        在每次执行inputEvent函数时,先清除上一次计时器,这样就只会执行最后一次计时器的回调函数。

三、形参传递

        如图所示,键盘输入的内容会出现很多种情况,"0232"需要使用parseInt(e.detail.value)转化为"232","adfs"通过parseInt转换后,会变成"NaN"。

        另外,在修正父组件中value值时,需要先把未校验的内容传给父组件中变量;例如:当父组件中值为0时,用户输入内容为-1200小于最小值0,校验后虽然给父组件中值重新赋值为0,但之前值为0未发生变化,此时输入框中还是显示-1200。所以此处需要先将错误值传递给父组件中的变量,再进行校验处理,这样则需要对旧值进行备份。

        对于JS中的计时器,很多人可能还不知道其能传递形参,这块知识在之前一篇中也讲述过,需要了解的可以去查看。地址:setTimeout和setInterval区别,以及定时器的传参功能-CSDN博客

setTimeout参数

参数描述
func必需。要执行的javascript代码串,也可以是一个函数
time必需。执行周期(毫秒数)
param1, param2, ...可选。传入执行函数其他参数

        将parseInt之后的新值,和之前旧值,通过计时器的形参传递到下个执行函数中,代码如下:

// 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,     // 是否禁用 减 按钮
    inputHandle: null,        // 计时器手柄
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 略...

    // 输入后  监听事件
    inputEvent(e){
      clearTimeout(this.inputHandle);
      // 开始计时
      this.inputHandle = setTimeout((nValue, oValue) => {
       
        console.log('e', oValue, nValue);
      }, 800, parseInt(e.detail.value), this.data.value);
    }
  }
})

        这样,像"032"之类新值,则会转换为正常数值传递到下次执行函数中;旧值则通过oValue往下传递,当父组件中value被替换后,this.data.value被修改,也不会影响到oValue,使其缓存到下次执行函数中备用。

四、判断是否为NaN

        当最后一次校验函数执行后,parseInt(e.detail.value)传递的新值如果为NaN,则将其置回来之前旧值,为了确保值能正常被更新,所以需要先将父组件中的变量赋值为未校验的值。代码如下:

// 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,     // 是否禁用 减 按钮
    inputHandle: null,        // 计时器手柄
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 略...

    // 输入后  监听事件
    inputEvent(e){
      clearTimeout(this.inputHandle);
      // 开始计时
      this.inputHandle = setTimeout((nValue, oValue) => {
        this.triggerMsg(e.detail.value);     // 先置为输入内容,后续校验后再相应调整
        // 判断内容是否为NaN
        if(isNaN(nValue)) {
          this.triggerMsg(oValue);
          return;
        }
        console.log('e', oValue, nValue);
      }, 800, parseInt(e.detail.value), this.data.value);
     
    }
  }
})

        此时,再输入像”adfs“之类内容,则会被置为之前旧值。当然,这里输入框input的类型为number,在手机端出现的键盘为 数字键盘,不会出现输入字母情况。但为程序严谨性,或以防某些平台存在兼容问题,还是需要考虑到这一步。

五、最小值和最大值校验

        对于最大值和最小值的校验,在上一篇中已有,并对之前判断稍作修改,这个大家慢慢细评、多思考。代码如下:

// 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,     // 是否禁用 减 按钮
    inputHandle: null,        // 计时器手柄
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 略...

    // 输入后  监听事件
    inputEvent(e){
      clearTimeout(this.inputHandle);
      // 开始计时
      this.inputHandle = setTimeout((nValue, oValue) => {
        this.triggerMsg(e.detail.value);     // 先置为输入内容,后续校验后再相应调整
        // 判断内容是否为NaN
        if(isNaN(nValue)) {
          this.triggerMsg(oValue);
          return;
        }
        // 判断值是否小于最小值
        if(this.data.min != null && this.data.min >= nValue) {
          this.triggerMsg(this.data.min);                   // 将值置为最小值
          this.setData({ isDisabledMul: true });            // 当底于最小值时,禁用 减 按钮
          // 如果减小按钮禁用,解除增加按钮的禁用
          if(this.data.isDisabledAdd) this.setData({ isDisabledAdd: false }); 
          return;
        } else if(this.data.isDisabledMul) {
          this.setData({ isDisabledMul: false }); 
        }
        // 判断值是否大于最大值
        if(this.data.max != null && this.data.max <= nValue)  {
          this.triggerMsg(this.data.max);                   // 将值置为最大值
          this.setData({ isDisabledAdd: true });            // 当超过最大值时,禁用 加 按钮 
          // 如果增加按钮禁用,解除减小按钮的禁用
          if(this.data.isDisabledMul) this.setData({ isDisabledMul: false }); 
          return;
        } else if(this.data.isDisabledAdd) {
          this.setData({ isDisabledAdd: false }); 
        }
        console.log('e', oValue, nValue);
      }, 800, parseInt(e.detail.value), this.data.value);

    }
  }
})

       此时,通过键盘输入内容后,如果不符合规范内容,或者超出限定范围的值,都会被立即纠正,并改回之前的值。如下图:

        上篇中addEvent事件函数和mulEvent事件函数中,都有对最大值和最小值的判断,如果觉得此处代码较为冗余,大家可以自行调整,合并代码。由于这里只是演示效果,就不细分了。

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

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

相关文章

亚马逊测评:提升产品信誉与销量的关键

在亚马逊这样竞争激烈的环境中。通过有效的测评&#xff0c;卖家可以轻松为自己的产品添加评论、提高排名&#xff0c;进而打造出优质的产品。然而&#xff0c;亚马逊测评并不等同于刷单。今天&#xff0c;将深入探讨亚马逊测评的本质、与刷单的区别&#xff0c;以及如何在这个…

新能源车燃料和动力电池及系统应用概述(上)

随着化石能源的日益消耗和对环保的逐渐重视&#xff0c;利用电能取代化石能源作为动力的电动汽车受到了世界各国的关注和大力研发。电池技术作为电动汽车的核心和瓶颈&#xff0c;是电动汽车研究的重点和热点方向&#xff0c;也是关系到新能源汽车成本、续航里程、安全性及使用…

【LLM大模型】一文掌握Prompt:万能框架+优化技巧+常用指标

随着大模型在2023年横空出世&#xff0c;“Prompt 工程” 应运而生&#xff0c;作为用好大模型最重要的武器&#xff0c;Prompt 的好坏对模型效果有着决定性的影响。然而&#xff0c;网络上大量相关文章多是罗列“Prompt 工程” 中的若干技巧&#xff0c;少有体系化的总结&…

gym/Gymnasium强化学习玩推箱子游戏

gym/Gymnasium强化学习玩推箱子游戏 gym 框架 源码 https://github.com/openai/gym 文档 https://www.gymlibrary.dev/ 自 2021 年以来一直维护 Gym 的团队已将所有未来的开发转移到 Gymnasium&#xff0c;这是 Gym 的替代品&#xff08;将 gymnasium 导入为 gym&#xff09;…

k8s工作负载控制器--DaemonSet

文章目录 一、概述二、适用场景三、基本操作1、官网的DaemonSet资源清单2、字段解释3、编写DaemonSet资源清单4、基于yaml创建DaemonSet5、注意点5.1、必须字段5.2、DaemonSet 对象的名称5.3、.spec.selector 与 .spec.template.metadata.labels之间的关系 6、查看DaemonSet6.1…

主成分分析和线性判别分析

主成分分析 (PCA) PCA 是一种线性降维方法&#xff0c;通过投影到主成分空间&#xff0c;尽可能保留数据的方差。 原理 PCA 通过寻找数据投影后方差最大的方向&#xff0c;主成分是这些方向上的正交向量。 公式推理 对数据中心化&#xff1a; 其中&#xff0c;μ 是数据的…

姿态矫正app-不良坐姿语音提示

“让爷康康”是一款应用于安卓平台的手机应用&#xff0c;可以实时监测不良坐姿并给出语音提示。本项目主要基于 [Tensorflow Lite 官方示例 - 姿态估计] 文件结构 ├───android │ ├───app │ │ └───src │ └───gradle ├───doc_images ├───…

科普文:JUC系列之Java中7种阻塞队列DelayQueue用法

阻塞队列DelayQueue是一种无界阻塞队列&#xff0c;‌用于放置实现了Delayed接口的对象。‌这些对象只能在其到期时才能从队列中取走&#xff0c;‌这种队列是有序的&#xff0c;‌即队头对象的延迟到期时间最长。‌如果没有任何延迟到期的对象&#xff0c;‌那么就不会有任何头…

示例:在ML.NET中应用Model Builder模型生成器构建图片对象检测模型

一、目的&#xff1a;ML.NET 是一个开源且跨平台的机器学习框架&#xff0c;专为 .NET 开发人员设计。它允许你在 .NET 应用程序中构建、训练和部署机器学习模型&#xff0c;而无需离开 .NET 生态系统。ML.NET 支持多种机器学习任务&#xff0c;包括分类、回归、聚类、异常检测…

五、栈与队列(2)

五、栈与队列&#xff08;2&#xff09; [150. 逆波兰表达式求值 ](https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/)[239. 滑动窗口最大值 ](https://leetcode.cn/problems/sliding-window-maximum/description/)[347.前 K 个高频元素 ](https:/…

python学习(day1)

1.Python 是大小写敏感的语言。 比如 print 函数名&#xff0c;该函数定义就是全部小写的&#xff0c; 不能写成 Print 或者 PRINT。 2.在Python语言中也会涉及到 对象&#xff0c; 这些对象包含了一定的数据信息。 Python语言中&#xff0c;所有的 数据 都被称之为 对象。 …

Docker 环境下使用 Traefik v3 和 MinIO 快速搭建私有化对象存储服务

上一篇文章中&#xff0c;我们使用 Traefik 新版本完成了本地服务网关的搭建。接下来&#xff0c;来使用 Traefik 的能力&#xff0c;进行一系列相关的基础设施搭建吧。 本篇文章&#xff0c;聊聊 MinIO 的单独使用&#xff0c;以及结合 Traefik 完成私有化 S3 服务的基础搭建…

C语言:qsort详解

在上一篇文章我们大致的了解了回调函数的用法和作用&#xff0c;在这一篇让我们来了解一下在回调函数qsort的使用吧。 一.qsort qsort是一种用来排各种类型数据的函数&#xff0c;利用的是快速排序的方式。说到排序&#xff0c;我们就想到了之前学习的冒泡排序&#xff0c;但…

MySQL数据如何高效实时同步到Elasticsearch?【送源码】

概述 在实际的项目开发与运维过程中&#xff0c;MySQL 常常扮演着业务数据库的核心角色&#xff0c;以其强大的事务处理能力和数据完整性保障&#xff0c;支撑着系统的稳定运行。然而&#xff0c;随着数据量的急剧增长和查询复杂度的不断提升&#xff0c;单一依赖 MySQL 进行高…

文章管理接口——里面有动态SQL编写,在分页查询里

1.实体类和表结构 2. 新增文章分类 接口文档 实现 完整代码放在校验部分 结果&#xff1a; 参数校验&#xff08;Validation自定义&#xff09; 对state的校验&#xff08;已发布|草稿&#xff09;&#xff0c;已有的注解不能满足校验需求&#xff0c;这时就需要自定义校验注解…

Day30 | 62.不同路径 63. 不同路径 II 343.整数拆分 96不同的二叉搜索树

语言 Java 62.不同路径 不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问…

JVM类加载中的双亲委派机制

【1】什么是双亲委派 Java虚拟机对class文件采用的是按需加载的方式&#xff0c;也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时&#xff0c;Java虚拟机采用的是双亲委派模式&#xff0c;即把请求交由父类处理&#xff0c…

【Git企业级开发实战指南①】Git安装、基本操作!

目录 一、Git是什么&#xff1f;1.1特点1.2功能1.3基本概念 二、Git安装2.1Ubuntu下安装2.2Centos下安装Git 三、Git基本操作3.1创建git本地仓库3.2配置Git3.3 工作区&暂存区&版本库3.4 实操案例3.4.1添加文件 3.5 修改文件3.6版本回退3.7查看历史操作日志3.7撤销修改3…

广东省各区县农业产量数据,数据精度至各区县,2020-2023年四年数据可选!

数据名称: 广东省各区县农业产量数据 数据格式: Shpexcel 数据几何类型: 面 数据坐标系: WGS84 数据时间&#xff1a;2020-2023年 数据来源&#xff1a;广东省统计年鉴 数据字段&#xff1a; 序号字段名称字段说明1province省份名称2city城市名称3county区县名称4cou…

【C++深度探索】红黑树的底层实现机制

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;C从入门至进阶 这里将会不定期更新有关C/C的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 前言 红…