如何在 Vue 中创建一个数字输入组件,其限制不允许超出限制范围

Cam*_*ilo 4 vue.js vuejs2

我正在尝试在 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>
Run Code Online (Sandbox Code Playgroud)
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
  }
})
Run Code Online (Sandbox Code Playgroud)

在这里小提琴:https : //jsfiddle.net/8dzhy5bk/6/

在前面的示例中,最大值设置为 50。如果我输入 60,它会在输入中自动转换为 50,但如果我输入第三个数字,则允许继续输入。传递给父级的值被限制,但我还需要限制输入,以便不能输入更多数字。

Sph*_*inx 5

当 input 的值大于 10 时,它总是会向父组件发出 10,但值保持不变(始终 = 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: {
  }
})
Run Code Online (Sandbox Code Playgroud)
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

以下是演示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: {
  }
})
Run Code Online (Sandbox Code Playgroud)
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)