项目需求 : 使用的饿了么组件库的 input 框 , 但是想要实现只能输入 数字 的功能,
So 看到了数字类型的验证 , 但今天在项目里对照着示例写都频繁报错 , 简直大无语 。 。 。
所以自己整理一下 , 免得自己以后掉坑 。 。 。
<template>
<div class="formBox">
<div class="infos">
<div class="infoBox">
<el-form
:model="numberValidateForm"
ref="numberValidateForm"
label-width="100px"
class="demo-ruleForm"
label-position="left"
>
<el-form-item label="姓名" prop="name" :rules="name">
<el-input
v-model="numberValidateForm.name"
autocomplete="off"
placeholder="请输入姓名"
></el-input>
</el-form-item>
<el-form-item label="联系电话" prop="phone" :rules="phone">
<el-input
v-model="numberValidateForm.phone"
autocomplete="off"
placeholder="请输入电话号码"
></el-input>
</el-form-item>
<el-form-item label="树龄" prop="number" :rules="number">
<el-input
type="number"
v-model.number="numberValidateForm.number"
autocomplete="off"
placeholder="请输入树龄"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('numberValidateForm')"
>提交</el-button
>
<el-button @click="resetForm('numberValidateForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
const cryptoJs = new CryptoJs();
export default {
data() {
let checkValue = (rule, value, callback) => {
if (!value) {
return callback(new Error("值不能为空"));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error("请输入数字值"));
} else {
if (value < 1) {
callback(new Error("值必须大于1"));
} else {
callback();
}
}
}, 200);
};
return {
numberValidateForm: {
name: "", // 姓名
phone: "", // 电话
number: null, // 数量
},
name: { required: true, message: "姓名不能为空" },
phone: { required: true, message: "联系电话不能为空" },
number: [
{ required: true, validator: checkValue, trigger: ["change", "blur"] },
],
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
let params = this.numberValidateForm;
console.log("验证成功,参数为", params);
} else {
console.log("数据验证不成功");
return false;
}
});
},
//重置
resetForm(formName) {
this.$refs[formName].resetFields();
},
},
};
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>
百度的各种写法 :(希望有一个能用得上吧)
<template>
<div class="formBox">
<div class="infos">
<div class="infoBox">
<el-form
:model="numberValidateForm"
ref="numberValidateForm"
label-width="100px"
class="demo-ruleForm"
label-position="left"
>
<el-form-item label="姓名" prop="name" :rules="name">
<el-input
v-model="numberValidateForm.name"
autocomplete="off"
placeholder="请输入姓名"
></el-input>
</el-form-item>
<el-form-item label="联系电话" prop="phone" :rules="phone">
<el-input
v-model="numberValidateForm.phone"
autocomplete="off"
placeholder="请输入电话号码"
></el-input>
</el-form-item>
<el-form-item label="树龄" prop="number" :rules="number">
<el-input
type="number"
v-model.number="numberValidateForm.number"
autocomplete="off"
placeholder="请输入树龄"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('numberValidateForm')"
>提交</el-button
>
<el-button @click="resetForm('numberValidateForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</template>
<script>
const cryptoJs = new CryptoJs()
export default {
data () {
let checkValue = (rule, value, callback) => {
if (!value) {
return callback(new Error('值不能为空'))
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'))
} else {
if (value < 1) {
callback(new Error('值必须大于1'))
} else {
callback()
}
}
}, 200)
}
return {
numberValidateForm: {
name: '', // 姓名
phone: '', // 电话
number: null // 数量
},
name: { required: true, message: '姓名不能为空' },
phone: { required: true, message: '联系电话不能为空' },
number: [{ required: true, validator: checkValue, trigger: ['change', 'blur'] }]
}
},
methods: {
submitForm (formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
let params = this.numberValidateForm
console.log('验证成功,参数为',params)
} else {
console.log('数据验证不成功')
return false
}
})
},
//重置
resetForm (formName) {
this.$refs[formName].resetFields()
}
}
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>
最后自己在项目中所用代码 :
<template>
<!-- 自定义校验规则 -->
<div class="formBox">
<!-- :model 绑定的一定要是一个 对象 numberValidateForm: {}
否则会报错 : 类型检查失败。应为对象,获取了值为 “” 的字符串 -->
<el-form
label-position="top"
:model="numberValidateForm"
ref="numberValidateForm"
label-width="200px"
class="demo-ruleForm"
>
<el-form-item size="mini">
<!-- 文本类型输入框 -->
<el-input
v-if="item.quInputType === '1'"
v-model="item.modelValue"
type="textarea"
:style="`width:${item.answerInputWidth}px`"
:rows="item.answerInputRow"
placeholder="请输入内容"
></el-input>
<!-- 日期类型输入框 -->
<el-date-picker
v-if="item.quInputType === '2'"
:readonly="true"
v-model="item.dateValue"
type="date"
placeholder="请选择日期"
></el-date-picker>
<!-- 数字类型输入框 -->
<!-- prop 要跟 rules 规则里的名字对应一致 -->
<el-form-item
v-if="item.quInputType === '3'"
prop="numValue"
:rules="numValue"
>
<el-input
size="small"
autocomplete="off"
type="numValue"
v-model.number="item.numberValidateForm.numValue"
:maxlength="item.numDigit"
@input="handleNumInput('numberValidateForm')"
placeholder="请输入数字"
></el-input>
</el-form-item>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
// 在 item 中的数据字段
numberValidateForm: {
numValue: "", // 数字输入框的绑定值
},
quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
modelValue: "", // 默认文本域绑定值
answerInputWidth: "300", // input 宽度
answerInputRow: "1", // input 高度
dateValue: "", // 日期选择器绑定值
numValue: [
{ required: true, message: "内容不能为空" },
{ type: "number", message: "内容必须为数字" },
],
numValue: "", // 数字输入框绑定值
numDigit: "1", // 控制数字位数
};
},
methods: {
handleNumInput(formName) {
// 输入时实时校验
/* 注意 : 这里有个大坑啊, 我的 this.$refs[formName]. 一直提示报错 : 不是一个函数
通过打印才发现层级出现了点问题, 改成 this.$refs[formName][0] 就 OK 了
也不知道是不是只有我的是如此 (如果你也出现了类似情况, 不妨就加上 [0] 试一试吧) */
this.$refs[formName][0].validate((valid) => {
if (valid) {
let params = this.numberValidateForm;
console.log("验证成功,参数为", params);
} else {
console.log("数据验证不成功");
return false;
}
});
},
},
};
</script>
<style lang="scss" scoped>
</style>
后来呢 , 这种方法只是能给到一个提示作用 , 并不能阻止到用户继续输入非数字内容 ,
所以继续百度搜寻方法 ,=> Vue 只能输入数字
不过呢这个有个问题就是使用的 v-bid:value , 来控制的输入框输入内容 ,
所以无法再使用 v-model 来进行双向绑定了 (缺点)
<template>
<div class="formBox">
<el-form label-position="top" label-width="200px" class="demo-ruleForm">
<el-form-item size="mini">
<!-- 文本类型输入框 -->
<el-input
v-if="item.quInputType === '1'"
v-model="item.modelValue"
type="textarea"
:style="`width:${item.answerInputWidth}px`"
:rows="item.answerInputRow"
placeholder="请输入内容"
></el-input>
<!-- 日期类型输入框 -->
<el-date-picker
v-if="item.quInputType === '2'"
:readonly="true"
v-model="item.dateValue"
type="date"
placeholder="请选择日期"
></el-date-picker>
<!-- 数字类型输入框 -->
<!-- :value 导致 v-model 双向绑定失效 -->
<!-- v-model.number="item.numValue" -->
<el-input
v-if="item.quInputType === '3'"
size="small"
:maxlength="item.numDigit"
@input="handleNumInput"
:value="inputNum"
placeholder="请输入数字"
></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
// 在 item 中的数据字段
numValue: "", // 数字输入框的绑定值
quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
modelValue: "", // 默认文本域绑定值
answerInputWidth: "300", // input 宽度
answerInputRow: "1", // input 高度
dateValue: "", // 日期选择器绑定值
numValue: "", // 数字输入框绑定值
numDigit: "1", // 控制数字位数
oldInputNum: "" /* 数字类型输入框初始值 */,
};
},
computed: {
inputNum() {
return this.oldInputNum;
},
},
methods: {
handleNumInput(event) {
/* 此方法因为使用了 v-bind:value , 所以原本的 v-model 双向绑定就不能使用了 ,
否则此方法会不生效 , 因此就需要我们自己去获取到用户最后输入的值了 */
// 缺点就是没有了双向绑定的便利性了
// let val = event.target.value.trim();
let val = event.trim();
// 只能是正整数或空,可根据需求修改正则
// item = e.target.value.replace(/[^\d]/g,'')
if (/^[1-9]\d*$|^$/.test(val)) {
this.oldInputNum = val;
} else {
// event.target.value = this.oldInputNum;
event = this.oldInputNum;
}
},
},
};
</script>
<style lang="scss" scoped>
</style>
最后使用了老项目里的代码方法 , 直接在 输入框上写 oninput
<el-input
oninput="this.value=this.value.replace(/\D/g,'')"
onafterpaste="this.value=this.value.replace(/\D/g,'')"
></el-input>
但是此方法不知为何 , 用户在输入完一些数字之后 , 再输入汉字时 , 可能会将所输入的数字删除掉 , 可能是正则的 replace 导致的 , 因此这还可能会影响到 v-model 的正常取值
只能通过获取用户最后一次输入的值赋值给 v-model 绑定的值了
<template>
<div>
<!-- 数字类型输入框 -->
<el-input
v-if="item.quInputType === '3'"
size="small"
:maxlength="item.numDigit"
v-model.number="item.numValue"
oninput="this.value=this.value.replace(/\D/g,'')"
@change="handleNumInput($event, item)"
placeholder="请输入数字"
></el-input>
</div>
</template>
<script>
export default {
data() {
return {
// 在 item 中的数据字段
numValue: "", // 数字输入框的绑定值
quInputType: "1", // input 类型 : 1.文本 2.日期 3.数字
modelValue: "", // 默认文本域绑定值
answerInputWidth: "300", // input 宽度
answerInputRow: "1", // input 高度
dateValue: "", // 日期选择器绑定值
numValue: "", // 数字输入框绑定值
numDigit: "1", // 控制数字位数
};
},
methods: {
handleNumInput(event, item) {
// 为了防止 v-model 失效 , 只好将最后一次输入的值赋值给绑定值了
item.numValue = event;
},
},
};
</script>
<style lang="scss" scoped>
</style>