Published Mar 13, 2017
众所周知,Vue 要限制输入还是比较麻烦的,如果使用双向绑定,在数据变化后再去做处理,输入内容会闪烁,体验并不是很好
想要输入不闪烁,就不能使用双向绑定了,那么有什么办法呢?
首先可以监听键盘输入事件,然后判断 event.target.value
的值,但是这也有个明显的缺点,那就是移动端不会触发 keyup/keypress/keydown 事件,所以比较好的方法就是监听 input
事件
虽然现在解决了输入限制,但是不能使用双向绑定也不是办法,如何使用双向绑定呢?
这个也不复杂,我们可以把这个输入限制封装成组件,然后给这个组件添加 v-model=”value” 属性,在组件内部声明 props:[‘value’],在限制输入的函数最后 emit 处理过后的值给父组件就完成了既能够输入限制,又支持双向绑定的组件了
示例代码:
<!-- parent.vue -->
<template>
<div id="app">
<common-input v-model="value" :fixed='fixed' :sum="sum" ></common-input>
</div>
</template>
<script>
import commonInput from './components/commonExchangeInput.vue'
export default {
name: 'app',
components: {
commonInput
},
data() {
return {
value: 0,
fixed: 5,
sum: 500
}
}
}
</script>
<!-- child.vue -->
<template>
<input type="text" @input="input($event)" :value="val">
</template>
<script>
export default {
props: ['value', 'fixed', 'sum'],
data() {
return {
val: ''
}
},
methods: {
input(ev) {
ev.target.value = ev.target.value.replace(/^0*(0\.|[1-9])/, '$1') // 解决 粘贴不生效
ev.target.value = ev.target.value.replace(/[^\d.]/g, '') // 清除“数字”和“.”以外的字符
ev.target.value = ev.target.value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
ev.target.value = ev.target.value
.replace('.', '$#$')
.replace(/\./g, '')
.replace('$#$', '.')
// ev.target.value = ev.target.value.replace(/^(\-)*(\d+)\.(\d\d\d\d).*$/, '$1$2.$3'); // 只能输入4个小数,且小数点前必须有数字
const length = this.fixed
const reg2 = new RegExp('^(-)*(\\d*?)\\.(\\d{1,' + length + '}).*$')
ev.target.value = ev.target.value.replace(reg2, '$1$2.$3') // 只能输入N个小数,小数点前面可以没有数字
if (ev.target.value.indexOf('.') < 0 && ev.target.value != '') {
// 如果没有小数点,首位不能为类似于 01、02的金额
if (
ev.target.value.substr(0, 1) == '0' &&
ev.target.value.length == 2
) {
ev.target.value = ev.target.value.substr(1, ev.target.value.length)
}
}
if (ev.target.value.indexOf('.') === 0 && ev.target.value.length > 1) {
// 如果第一个字符时“.”,那么当“.”后面有数字后,"."前面自动补零
ev.target.value = 0 + ev.target.value
}
if (this.sum) {
if (Number(ev.target.value) > Number(this.sum)) {
ev.target.value = this.sum
}
}
this.val = ev.target.value
this.$emit('input', this.val)
}
}
}
</script>