首页 > 解决方案 > 如何在 Vue 中创建一个数字输入组件,其限制不允许超出限制

问题描述

我正在尝试在 Vue 中创建一个数字输入组件,其最小值和最大值不允许在没有成功的情况下在外部限制之外键入:

<template id="custom-input">
  <div>
    <input :value="value" type="number" @input="onInput">
  </div>
</template>

<div id="app">
  <div>
    <span>Value: {{ value }}</span>
    <custom-input v-model="value" :max-value="50"/>
  </div>
</div>
Vue.component('custom-input', {
  template: '#custom-input',
  props: {
    value: Number,
    maxValue: Number
  },
  methods: {
    onInput(event) {
      const newValue = parseInt(event.target.value)
      const clampedValue = Math.min(newValue, this.maxValue)
      this.$emit('input', clampedValue)
    }
  }
})

new Vue({
  el: "#app",
  data: {
    value: 5
  }
})

在这里摆弄:https ://jsfiddle.net/8dzhy5bk/6/

在前面的示例中,最大值设置为 50。如果我输入 60,它会在输入中自动转换为 50,但如果我输入第三个数字,它允许继续输入。传递给父级的值是固定的,但我还需要限制输入,这样就不能再输入数字了。

标签: vue.jsvuejs2

解决方案


当 input 的值大于 10 时,它总是会向父组件发出 10,但值保持不变(always=10)所以它不会触发 reactvity

一种解决方案,总是parseInt(event.target.value)先发出实际值(=),然后发出最大值(= Math.min(newValue, this.maxValue)vm.$nextTick()

另一种解决方案是使用this.$forceUpdate().

下面是. _$nextTick

Vue.component('custom-input', {
  template: '#custom-input',
  props: {
    value: Number,
    maxValue: Number
  },
  methods: {
    onInput(event) {
      const newValue = parseInt(event.target.value)
      const clampedValue = Math.min(newValue, this.maxValue)
      this.$emit('input', newValue)
      this.$nextTick(()=>{
      	this.$emit('input', clampedValue)
      })
    }
  }
})

new Vue({
  el: "#app",
  data: {
    value: 5
  },
  methods: {
  }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>

<template id="custom-input">
  <div>
    <input 
      :value="value" 
      type="number" 
      @input="onInput" 
     >
  </div>
</template>

<div id="app">
  <div>
    <span>Value: {{ value }}</span>
    <custom-input v-model="value" :max-value="10"/>
  </div>
</div>

下面是. _vm.$forceUpdate

Vue.component('custom-input', {
  template: '#custom-input',
  props: {
    value: Number,
    maxValue: Number
  },
  methods: {
    onInput(event) {
      const newValue = parseInt(event.target.value)
      const clampedValue = Math.min(newValue, this.maxValue)
      this.$emit('input', clampedValue)
      this.$forceUpdate()
    }
  }
})

new Vue({
  el: "#app",
  data: {
    value: 5
  },
  methods: {
  }
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>

<template id="custom-input">
  <div>
    <input 
      :value="value" 
      type="number" 
      @input="onInput" 
     >
  </div>
</template>

<div id="app">
  <div>
    <span>Value: {{ value }}</span>
    <custom-input v-model="value" :max-value="10"/>
  </div>
</div>


推荐阅读