笔记移动端H5数字键盘input type=number的处理(IOS和Android)

Posted simlesmith

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记移动端H5数字键盘input type=number的处理(IOS和Android)相关的知识,希望对你有一定的参考价值。

在Vue中的项目,基于VUX-UI开发,一个常见的需求:

1、金额输入框

2、弹出数字键盘

3、仅支持输入两位小数,限制最大11位数,不允许0开头  

 

第一,首先想到额就是在VUX-UI中制定type=number。--不可行

  VUX中的文档和代码说明,type=number不支持maxLength,会报错,而且没有正则替换的处理或者钩子函数,只有输入后提示校验信息。

第二,基于VUX中XInput封装,有如下问题

  1)两层v-model,正则替换的值不会触发input框渲染

  解决:currentValue赋值为foramttedValue,放入setTimeout(func ,0)中,让input框先渲染为正则替换前的值,再渲染为替换后的值

技术分享图片
    currentValue(val, oldVal) {
      // 调用filter过滤数据
      let formattedValue = this.filter(val);
      if (this.type === ‘number‘) {
        formattedValue = this.typeNumberFilter(formattedValue, oldVal);
      }
      if (val !== formattedValue || val === ‘‘) {
        setTimeout(() => {
          this.currentValue = formattedValue;
        }, 0);
      }
      this.$emit(‘input‘, formattedValue);
    },
View Code

  2)数字键盘input type=number,会导致maxlength失效,无法限制长度

  解决:用slice(0, max)处理

技术分享图片
      if (formattedValue.length > this.max) {
        formattedValue = formattedValue.slice(0, this.max);
      }
View Code

  3)数字键盘input type=number ,连续输入小数点...导致实际值和显示值不一致

  解决:用原生的 inputElement.value = oldValue处理

技术分享图片
      const inputEle = this.$children[0].$refs.input;
      // TODO: 待大范围验证:处理连续输入..后,type=number的input框会把值修改为‘‘的问题;fastclick导致type=number报错
      // 问题描述: 1.00. 不会触发值改变,1.00.不会触发值改变,1.00.【\d\.】都会把值修改为空字符串‘‘。hack处理的条件说明如下:
      // 1、当校验后是空值,(因input=number,formattedValue为‘‘表明 原始newVal也为‘‘)
      // 2、输入框拿到的是空值(因input=number导致输入框立即被赋予空值。点击清除按钮时,这里input输入框还是上次的值)
      // 3、上次输入大于两位(避免最后一位无法删除的问题。最后一位删除时,oldVal.length === 1)
      if (formattedValue === ‘‘ && inputEle.value === ‘‘ && oldVal && oldVal.match(/^(\d)[\d.]+/)) {
        formattedValue = oldVal;
      }
      setTimeout(() => {
        inputEle.value = formattedValue;
      }, 0);
View Code

   4)ios中数字键盘有%$*等特殊字符

  解决:用原生的 inputElement.onkeydown监听事件,非数字和退格和小数点直接return事件

技术分享图片
  mounted() {
    if (this.type === ‘number‘) {
      const inputEle = this.$refs.xinput.$refs.input;
      // eslint-disable-next-line
      inputEle.onkeydown = (e) => {
        const keyCode = e.keyCode;
        if (!this.isBackspace(keyCode) && !this.isDot(keyCode) && !this.isNumber(keyCode)) {
          // 其他按键
          e.preventDefault();
          e.stopPropagation();
          return false;
        }
      };
    }
  }
View Code

 

第三,其他说明

  为什么不用 type=tel?

    type=tel在ios中没有小数点

 

第四,全部代码

 

技术分享图片
<template>
  <XInput
    :title="title"
    :max="currentMax"
    :min="currentMin"
    :type="type"
    v-model="currentValue"
    @on-focus="onFoucus()"
    @on-blur="onBlur()"
    :show-clear="showClear"
    :placeholder="placeholder"
    ref="xinput">
    <template v-if="$slots.label" slot="label"><slot name="label"></slot></template>
    <template v-if="$slots.right" slot="right"><slot name="right"></slot></template>
  </XInput>
</template>

<script>

export default {
  data() {
    return {
      currentValue: this.value,
    };
  },
  computed: {
    currentMax() {
      return (this.type === ‘number‘) ? undefined : this.max;
    },
    currentMin() {
      return (this.type === ‘number‘) ? undefined : this.min;
    }
  },
  props: {
    title: String,
    max: Number,
    min: Number,
    type: String,
    showClear: {
      type: Boolean,
      default: true,
    },
    placeholder: String,
    value: [String, Number],
    filter: {
      type: Function,
      default: (value) => {
        let formattedValue = ‘‘;
        const match = value.match(/^([1-9]\d*(\.[\d]{0,2})?|0(\.[\d]{0,2})?)[\d.]*/);
        if (match) {
          formattedValue = match[1];
        }
        return formattedValue;
      },
    }
  },
  watch: {
    currentValue(val, oldVal) {
      // 调用filter过滤数据
      let formattedValue = this.filter(val);
      if (this.type === ‘number‘) {
        formattedValue = this.typeNumberFilter(formattedValue, oldVal);
      }
      if (val !== formattedValue || val === ‘‘) {
        setTimeout(() => {
          this.currentValue = formattedValue;
        }, 0);
      }
      this.$emit(‘input‘, formattedValue);
    },
    value(value) {
      this.currentValue = value;
    },
  },
  methods: {
    onFoucus() {
      this.$emit(‘on-focus‘);
    },
    onBlur() {
      this.$emit(‘on-blur‘);
    },
    typeNumberFilter(val, oldVal) {
      const inputEle = this.$refs.xinput.$refs.input;
      let formattedValue = val;
      // 由于type=number不支持maxLength,用slice模拟
      if (formattedValue.length > this.max) {
        formattedValue = formattedValue.slice(0, this.max);
      }
      // TODO: 待大范围验证:处理连续输入..后,type=number的input框会把值修改为‘‘的问题;fastclick导致type=number报错
      // 问题描述: 1.00. 不会触发值改变,1.00.不会触发值改变,1.00.【\d\.】都会把值修改为空字符串‘‘。hack处理的条件说明如下:
      // 1、当校验后是空值,(因input=number,formattedValue为‘‘表明 原始newVal也为‘‘)
      // 2、输入框拿到的是空值(因input=number导致输入框立即被赋予空值。点击清除按钮时,这里input输入框还是上次的值)
      // 3、上次输入大于两位(避免最后一位无法删除的问题。最后一位删除时,oldVal.length === 1)
      if (formattedValue === ‘‘ && inputEle.value === ‘‘ && oldVal && oldVal.match(/^(\d)[\d.]+/)) {
        formattedValue = oldVal;
      }
      setTimeout(() => {
        inputEle.value = formattedValue;
      }, 0);
      return formattedValue;
    },
    isBackspace(keyCode) {
      return keyCode === 8;
    },
    isDot(keyCode) {
      return keyCode === 46 || keyCode === 110 || keyCode === 190;
    },
    isNumber(keyCode) {
      return (keyCode >= 48 && keyCode <= 57) || (keyCode >= 96 && keyCode <= 105);
    },
  },
  mounted() {
    if (this.type === ‘number‘) {
      const inputEle = this.$refs.xinput.$refs.input;
      // eslint-disable-next-line
      inputEle.onkeydown = (e) => {
        const keyCode = e.keyCode;
        if (!this.isBackspace(keyCode) && !this.isDot(keyCode) && !this.isNumber(keyCode)) {
          // 其他按键
          e.preventDefault();
          e.stopPropagation();
          return false;
        }
      };
    }
  }
};
</script>
View Code

 

以上是关于笔记移动端H5数字键盘input type=number的处理(IOS和Android)的主要内容,如果未能解决你的问题,请参考以下文章

移动端H5页面_input获取焦点时,虚拟键盘挡住input输入框解决方法

移动端开发,H5对number输入框的一些处理

移动端H5 input输入完成后页面底部留白问题

移动端H5监听键盘弹出和收起

移动端input type=“file” 在移动端H5页面实现调用本地相册拍照录音

H5移动端页面加入canvas可滑动代码条件下android手机点击input重复弹出键盘