我正在尝试在 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,但如果我输入第三个数字,则允许继续输入。传递给父级的值被限制,但我还需要限制输入,以便不能输入更多数字。
当 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)