需求:
1.系统内所有金额输入框,只允许输入数字且只允许小数点两位
2.系统内所有数字输入框,只允许输入数字
兼容浏览器:谷歌浏览器,Edge浏览器,火狐浏览器
问题:
1.由于火狐浏览器直接用全局指令限制输入会有很多问题,故封装成全局组件的形式使用
2.input自带的type=number和type=tel都存在特殊符号,无法满足需求
封装一个全局组件GlobalInput.vue,组件代码如下:
<template>
<el-input
:placeholder="placeholder"
v-model="inputVal"
:maxlength="maxlength"
:disabled="disabled"
:clearable="clearable"
:plain="plain"
:min="min"
:class="className"
:style="styles"
:size="size"
@input="handleInput($event)"
@change="change"
@blur="blur"
>
<template slot="append" v-if="hasAppend">{{ appendContent }}</template>
</el-input>
</template>
<script>
export default {
props: {
placeholder: {
type: [String, Number],
default: '',
},
value: {
type: [String, Number],
default: '',
},
plain: {
type: Boolean,
default: false,
},
clearable: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
size: {
type: String,
default: '',
},
min: {
type: [String, Number],
default: '',
},
className: {
type: String,
default: '',
},
styles: {
type: [String, Object],
default: '',
},
maxlength: {
type: [String, Number],
default: -1,
},
hasAppend: {
// 是否有append 插槽
type: Boolean,
default: false,
},
appendContent: {
type: String,
default: '',
},
/**
* @param type
* number:数字输入框,只允许输入数字
* price: 金额输入框,保留两位小数
*/
type: {
type: String,
default: 'productCode',
},
},
data() {
return {
inputVal: '',
number: /\D/g,
// 此处可以添加任意key,值为对应正则表达式,如添加下面正则,在外面使用时,就可以直接type="minNumber"限制输入框不能输入小于1的数字
minNumber: /^(0+)|\D/g, // 不能输入小于1的数字
}
},
watch: {
value: {
handler(val) {
this.inputVal = val
},
deep: true,
immediate: true, // 回显值使用
},
},
methods: {
handleInput(v) {
let formatValue
if (this.type === 'price') {
// 金额输入框处理(比较复杂的输入框限制逻辑,单独限制)
formatValue =
('' + v) // 第一步:转成字符串
.replace(/[^\d^\.]+/g, '') // 第二步:把不是数字,不是小数点的过滤掉
.replace(/^0+(\d)/, '$1') // 第三步:第一位0开头,0后面为数字,则过滤掉,取后面的数字
.replace(/^\./, '0.') // 第四步:如果输入的第一位为小数点,则替换成 0. 实现自动补全
.match(/^\d*(\.?\d{0,2})/g)[0] || '' // 第五步:最终匹配得到结果 以数字开头,只有一个小数点,而且小数点后面只能有0到2位小数
} else {
// 其他输入框处理
formatValue = v.replace(this[this.type], '')
}
this.inputVal = formatValue
this.$emit('update:value', formatValue)
this.$emit('input', formatValue)
},
change(v) {
this.$emit('change', v)
},
blur(e) {
this.$emit('blur', e)
},
},
}
</script>
使用示例:(与el-input的写法只有两处不同:)
1.v-model换成:value.sync
2.type换成我们自定义的type
<global-input
type="price" // 1.price: 金额输入框,保留两位小数 2.number:数字输入框,只允许输入数字 3.其它自定义type对应正则
:value.sync="form.price" // 双向数据绑定的值
clearable
placeholder="请填写金额"
size="mini"
maxlength="10"
:disabled="disabled"
></global-input>
ps:这里是最简单的封转,建议根据自己的场景进行加入属性继承v-bind="$attrs"和插槽继承等