简体   繁体   English

文本输入只需要一位或多个相同的数字

[英]text input only takes one digit or multiple identical digits

I'm using Vue.js and would like to create a input field component that only takes positive integers (0 is fine too).我正在使用 Vue.js 并想创建一个只接受正整数的输入字段组件(0 也可以)。 I would like to avoid using regex to keep it human readable :)我想避免使用正则表达式来保持人类可读:)

My consuming parent component passes in the current value and uses the shorthand sync directive我的消费父组件传入当前值并使用速记同步指令

<template>
  <div>
    <form>
      <positive-integer-input :value.sync="currentValue" />
    </form>
  </div>
</template>

<script>
import PositiveIntegerInput from "../components/PositiveIntegerInput.vue";

export default {
  components: {
    "positive-integer-input": PositiveIntegerInput
  },
  data() {
    return {
      currentValue: 0
    };
  }
};
</script> 

The input component itself is just a basic text input (for better CSS styling)输入组件本身只是一个基本的文本输入(为了更好的 CSS 样式)

<template>
  <input :id="_uid" type="text" :value="value" @input="onInput" />
</template>

<script>
export default {
  props: {
    value: {
      type: Number,
      required: true
    }
  },
  methods: {
    onInput({ data }) {
      const inputNumber = Number(data);

      if (!Number.isInteger(inputNumber) || inputNumber < 0) {
        const input = document.getElementById(this._uid);
        input.value = this.value;
      } else {
        this.$emit("update:value", inputNumber);
      }
    }
  }
};
</script>

Whenever the input changes I'm validating the incoming input for positive integers.每当输入更改时,我都会验证传入的输入是否为正整数。 If that validation fails I want to reset the current input field content (maybe there is a more userfriendly solution?)如果验证失败,我想重置当前的输入字段内容(也许有更用户友好的解决方案?)

The input field itself only takes one digit or multiple identical digits.输入字段本身只需要一个数字或多个相同的数字。 So only these are possible:所以只有这些是可能的:

  • 3 3
  • 4 4
  • 333333 333333
  • 4444 4444

but not:但不是:

  • 34 34

Does someone know how to fix the component?有人知道如何修复组件吗?

Thanks in advance提前致谢

I'm still not entirely sure I understand the requirements but I think this is somewhere close to what you're looking for:我仍然不完全确定我了解要求,但我认为这与您要寻找的东西很接近:

 const PositiveIntegerInput = { template: ` <input ref="input" type="text" :value="value" @input="onInput" > `, props: { value: { type: Number, required: true } }, methods: { onInput(ev) { const value = ev.target.value; const inputNumber = parseInt(value, 10); if (inputNumber >= 0 && String(inputNumber) === value) { this.$emit('update:value', inputNumber); } else { // Reset the input if validation failed this.$refs.input.value = this.value; } } } }; new Vue({ el: '#app', components: { PositiveIntegerInput }, data () { return { currentValue: 0 } } })
 <script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script> <div id="app"> <div> <form> <positive-integer-input :value.sync="currentValue" /> </form> </div> </div>

I've used $refs instead of document.getElementById to perform the reset.我使用$refs而不是document.getElementById来执行重置。

To check the input is an integer I've simply converted it to an integer using parseInt , then converted it back to a string and compared that to the original string.为了检查输入是一个整数,我只是使用parseInt将其转换为整数,然后将其转换回字符串并将其与原始字符串进行比较。

There are several edge cases that could cause problems.有几种边缘情况可能会导致问题。 A particularly obvious one is that the input can never be empty, which makes changing an existing value quite difficult.一个特别明显的问题是输入永远不能为空,这使得更改现有值非常困难。 However, as far as I can tell, this does meet the requirements given in the question.但是,据我所知,这确实符合问题中给出的要求。

Update:更新:

A few notes on number parsing.关于数字解析的一些注意事项。

Using Number(value) will return NaN if it can't parse the entire string.如果无法解析整个字符串,则使用Number(value)将返回NaN There are some quirks with using Number too.使用Number也有一些怪癖。 eg Try Number('123e4') , Number('0x123') or Number('0b11') .例如,尝试Number('123e4')Number('0x123')Number('0b11')

Using parseInt(value, 10) will parse as many characters as it can and then stop.使用parseInt(value, 10)将解析尽可能多的字符,然后停止。 parseInt also has some quirks but by explicitly specifying a radix of 10 they mostly go away. parseInt也有一些怪癖,但通过明确指定10的基数,它们通常会消失。

If you try to parse '53....eeöööööö' using parseInt you'll get 53 .如果您尝试使用parseInt解析'53....eeöööööö'您将得到53 This is an integer, so it'll pass a Number.isInteger test.这是一个整数,因此它将通过Number.isInteger测试。

Personally I'd like to have used a RegExp to ensure the string only contains digits 0-9 before doing any further manipulation.我个人希望在进行任何进一步操作之前使用 RegExp 来确保字符串仅包含数字 0-9。 That quickly helps to eliminate a whole load of possible edge cases such that they wouldn't need any further consideration.这很快有助于消除大量可能的边缘情况,这样它们就不需要任何进一步的考虑。 Something like /^\\d*$/.test(value) , or the converse !/\\D/.test(value) .类似于/^\\d*$/.test(value) ,或者相反的!/\\D/.test(value)

For the sake of completeness I tried to improve Skirtles answer.为了完整起见,我试图改进裙子的答案。 So the component consumer remains the same, only the input component changes a little bit.所以组件消费者保持不变,只有输入组件发生了一点变化。 Now it's possible to leave the input empty but the value won't trigger an update then.现在可以将输入留空,但该值不会触发更新。 Also the input field adds some visual styles based on the validation.此外,输入字段根据验证添加了一些视觉样式。

<template>
  <input
    type="text"
    :value="value"
    @input="onInput"
    :class="[inputValueIsValid ? 'valid-input' : 'invalid-input']"
  />
</template>

<script>
export default {
  props: {
    value: {
      type: Number,
      required: true
    }
  },
  data() {
    return {
      digitsOnlyRegex: /^\d*$/,
      inputValueIsValid: false
    };
  },
  mounted() {
    this.validateInputValue(this.value);
  },
  methods: {
    onInput(inputEvent) {
      const currentInputValue = inputEvent.target.value;
      this.validateInputValue(currentInputValue);

      if (this.inputValueIsValid) {
        const inputNumber = parseInt(currentInputValue, 10);
        this.$emit("update:value", inputNumber);
      }
    },
    validateInputValue(currentInputValue) {
      const isNotEmpty = currentInputValue.toString().length > 0;
      const containsDigitsOnly = this.digitsOnlyRegex.test(currentInputValue);
      this.inputValueIsValid = isNotEmpty && containsDigitsOnly;
    }
  }
};
</script>

<style scoped>
.valid-input {
  background: green;
}

.invalid-input {
  background: red;
}
</style>

Your problem is here:你的问题在这里:

const input = document.getElementById(this._uid);
input.value = this.value;

Use v-model instead or try to replace code by this:改用v-model或尝试通过以下方式替换代码:

<template>
  <input :id="_uid" type="text" :value="inputValue" @input="onInput($event.target.value, $event)" />
</template>

<script>
export default {
  data(){
    return inputValue: 0,
  },
  props: {
    value: {
      type: Number,
      required: true
    }
  },
  created(){
    this.inputValue = this.value;
  },
  methods: {
    onInput(value, event) {
      const inputNumber = Number(value);

      if (!Number.isInteger(inputNumber) || inputNumber < 0) {
        this.inputValue = this.value;
      } else {
        this.$emit("update:value", inputNumber);
      }
    }
  }
};
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 屏蔽输入文字,仅输入4位数字 - Masking to input type text to only 4 digits 输入数字必须是 6 位数字或 9 位数字 - Input numbers must be 6 digit numbers or 9 digits numbers 如何在 html 文本输入中只允许 2 位数字,用冒号分隔? - How to allow only 2 digit numbers in html text input separated by colon? 单个数字和仅带小数的单个数字的正则表达式 - Regex for single digits and single digit with decimal only jQuery输入中只有数字 - jQuery only digits in input ReactJS:一位数字输入可以以多个“0”结尾 - ReactJS: one digit input can end up with multiple '0's 如何验证输入文本允许第一和第二位数字仅为字母 - How to verify that the input text allows the first and second digits to be only letters 在 angular 中仅将输入绑定到一个文本输入 - Bind input to only one text input in angular 文本输入字段末尾有 static 文本,只允许输入数字而没有可选择的文本? - text input field with static text at the end, only allowing to enter digits without without text selectable? 我正在尝试输出一种数字模式,该模式接受输入并下降然后一次上升到原始数字一位 - I am attempting to output a pattern of numbers that takes an input and descends then ascends back up to the original number one digit at a time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM