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

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

        计数器的实现主要涉及到几个关键部分,上一篇已重点讲过,该篇将讲述一下中间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事件函数中,都有对最大值和最小值的判断,如果觉得此处代码较为冗余,大家可以自行调整,合并代码。由于这里只是演示效果,就不细分了。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信小程序是一种基于微信平台的应用的开发模式,可以快速的开发出符合用户需求的小程序。在小程序的开发中,组件是一个非常重要的概念,通过组件可以实现复用性和模块化编程思想。 组件应用是小程序开发的基础。通过组件可以将某一模块化并封装起来,使得组件可以在不同的页面间得到复用,大大提升了开发效率并减少了代码冗余。微信小程序提供了丰富的自带组件,包括文本、图片、按钮、输入框等等,开发者也可以自己开发组件来满足自己的需求。实际开发中,通过组件可以快速搭建页面框架和业务逻辑。 Demo是一个演示小程序的示例程序。在小程序的实际开发过程中,一个好的Demo非常重要。通过Demo,开发人员可以更深入的了解小程序的开发流程、组件的应用和实际的业务开发等等。在Demo中,通常会包括小程序的一些基础操作,如页面跳转、数据绑定、组件的使用等。而在实际开发中,Demo还会包括一些复杂的业务场景,如支付、登录、数据列表展示等等。Demo不仅为开发者提供了学习和实践的机会,也方便了使用者了解该小程序的功能和特点。 总之,微信小程序组件的应用和Demo的开发都是小程序开发过程中非常重要的两个部分。良好的组件应用和精心设计的Demo,可以在极短的时间内实现小程序开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值