Elment-UI 的 Form 組件提供了表單驗證的功能:
1.將 Form-Item 的 prop
屬性設(shè)置為需校驗的字段名
2.通過 rules
屬性傳入約定的驗證規(guī)則
rules: {
name: [
{
required: true, //非空校驗
message: '提示信息', //校驗提示信息
trigger: 'blur'//觸發(fā)條件:blur、change
}
]
踩坑:
1.要驗證輸入只能為數(shù)字時
{type:'number',message:'只能為數(shù)字'}
必須要在v-model后面加上.number,即v-moder.number。這里的驗證會將你輸入的value格式化為number值摘完,在你做自定義校驗的時候踢关,要格外注意,有可能正則表達式?jīng)]有起到效果荷荤,就是因為它自動給你轉(zhuǎn)化格式了
2.自定義校驗
必須要有回調(diào),否則表單無法提交。
data() {
var newReg1 = (rule, value, callback) => {
if (value < 0) {
callback(new Error("不能為負數(shù)"));
} else {
callback(); //必須要有回調(diào)袒哥,要不然表單無法提交
}
};
var newReg2 = (rule, value, callback) => {
let pattrn = /^((?!0)\d+(\.\d{1,2})?)$/g
if (!pattrn.test(value)) {
callback(new Error("不能為負數(shù)"));
} else {
callback();
}
};
return {
amountCheck: [
{ validator: newReg1, trigger: "blur" },
{ validator: newReg2, trigger: "blur" },
//此處可寫多個校驗方法
......
]
};
}
3.數(shù)據(jù)綁定
做表單驗證時<el-form-item>必須添加prop屬性,而且prop的名字必須和input框v-model綁定的值一致消略。否則的話堡称,表單驗證就會出錯。
<el-form-item label="活動名稱" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
不同類型的表單校驗
1.普通輸入驗證
<el-form-item label="活動名稱" prop="name">
<!-- validate-event屬性的作用是: 輸入時不觸發(fā)表單驗證.提交時再驗證,你也可以設(shè)置成動態(tài)驗證 -->
<el-input v-model="registData.name" :validate-event="false"></el-input>
</el-form-item>
rules: { // 表單驗證規(guī)則
name: [
{ required: true, message: '請輸入活動名稱' }, // 'blur'是鼠標失去焦點的時候會觸發(fā)驗證
{ min: 3, max: 5, message: '長度在 3 到 5 個字符' }
]
}
2.數(shù)字類型驗證
<el-form-item label="區(qū)域面積" prop="area">
<!-- 輸入的類型為Number時,需要加一個數(shù)字轉(zhuǎn)換的修飾符,輸入框默認的類型是String類型,但是我試了一下,發(fā)現(xiàn)并不能做驗證,所以自己寫了函數(shù)方法驗證 -->
<!-- <el-input v-model.number="registData.area" autocomplete="off"></el-input> -->
<!-- keyup是鼠標彈起事件, autocomplete是input自帶的原生屬性,自動補全功能,on為開啟,off為關(guān)閉 -->
<el-input v-model="registData.area" @keyup.native="InputNumber('area')" autocomplete="off"></el-input>
</el-form-item>
area: [
// 數(shù)字類型 'number', 整數(shù): 'integer', 浮點數(shù): 'float'
// {type: 'number', message: '請輸入數(shù)字類型', trigger: 'blur'},
// {type: 'integer', message: '請輸入數(shù)字類型', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發(fā)驗證
{required: true, message: '請輸入?yún)^(qū)域面積', trigger: 'blur'}
],
// 自己寫的正則驗證,限制用戶輸入數(shù)字以外的字符
// 過濾輸入的金額
InputNumber (property) {
this.registData[property] = this.limitInputPointNumber(this.registData[property])
},
// 驗證只能輸入數(shù)字
limitInputNumber (val) {
if (val) {
return String(val).replace(/\D/g, '')
}
return val
},
// 限制只能輸入數(shù)字(可以輸入兩位小數(shù))
limitInputPointNumber (val) {
if (val === 0 || val === '0' || val === '') {
return ''
} else {
let value = null
value = String(val).replace(/[^\d.]/g, '') // 清除“數(shù)字”和“.”以外的字符
value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多余的
value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數(shù)
return Number(value)
}
},
3.1 嵌套驗證(獨立驗證)
這種情況是一行里有多個輸入框或選擇的情況,這里有兩種方法,第一種是el-form嵌套寫法,驗證是獨立的
<el-form-item label="活動時間" required>
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker type="date" placeholder="選擇日期" v-model="registData.date1" style="width: 100%;"></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker type="fixed-time" placeholder="選擇時間" v-model="registData.date2" style="width: 100%;"></el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
date1: [
{ type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
],
date2: [
{ type: 'date', required: true, message: '請選擇時間', trigger: 'change' }
],
3.2 嵌套驗證(聯(lián)動驗證)
這種是聯(lián)動驗證,適用省級聯(lián)動場景,先選國家后觸發(fā)城市驗證
<!-- region是一個對象,國家和城市是它的屬性 -->
<el-form-item label="活動區(qū)域" prop="region">
<el-select v-model="registData.region.country" placeholder="請選擇國家">
<el-option label="國家一" value="USA"></el-option>
<el-option label="國家二" value="China"></el-option>
</el-select>
<el-select v-model="registData.region.city" placeholder="請選擇城市">
<el-option label="城市一" value="shanghai"></el-option>
<el-option label="城市二" value="beijing"></el-option>
</el-select>
</el-form-item>
region: [
{
type: 'object',
required: true,
// 這里有兩種處理,一種是自定義驗證,拿到值后自己對屬性進行驗證,比較麻煩
// validator: (rule, value, callback) => {
// console.log(55, value)
// if (!value.country) {
// callback(new Error('請選擇國家'))
// } else if (!value.city) {
// callback(new Error('請選擇城市'))
// } else {
// callback()
// }
// },
trigger: 'change',
// 官網(wǎng)提供了對象的嵌套驗證,只需要把需要驗證的屬性,放在fields對象里,就會按順序進行驗證
fields: {
country: {required: true, message: '請選擇國家', trigger: 'blur'},
city: {required: true, message: '請選擇城市', trigger: 'blur'}
}
}
],
4.圖片上傳驗證(手動觸發(fā)部分驗證方法)
有時候會需要在表單里上傳圖片,但是圖片上傳是一個異步過程,屬性值改變后不會去觸發(fā)驗證規(guī)則
文件上傳后艺演,不會觸發(fā)form表單的驗證却紧,需要手動調(diào)用校驗方法。
<el-form-item label="活動圖片" prop="fileUrl">
<el-upload
:action="action"
:on-success="handleSuccess"
:data="uploadData"
:limit="20"
list-type="picture-card"
:on-preview="handlePreview"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
fileUrl: [
{ required: true, message: '請上傳圖片', trigger: 'change' }
],
// 刪除圖片
handleRemove (file, fileList) {
this.registData.fileUrl = ''
// 文件刪除后也要觸發(fā)驗證,validateField是觸發(fā)部分驗證的方法,參數(shù)是prop設(shè)置的值
this.$refs.registerRef.validateField('fileUrl')
},
// 圖片上傳
handleSuccess (res, file, fileList) {
// 這里可以寫文件上傳成功后的處理,但是一定要記得給fileUrl賦值
this.registData.fileUrl = 'fileUrl'
// 文件上傳后不會觸發(fā)form表單的驗證,要手動添加驗證
this.$refs.registerRef.validateField('fileUrl')
},
表單校驗示例:(包含自定義校驗)
<el-form :model="ruleForm" :rules="rules" ref="ruleForm">
<!--input輸入框-->
<el-form-item label="活動名稱" prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<!--自定義校驗-->
<el-form-item label="聯(lián)系電話" prop="phone">
<el-input v-model="ruleForm.phone"></el-input>
</el-form-item>
<!--select下拉框-->
<el-form-item label="活動區(qū)域" prop="region">
<el-select v-model="ruleForm.region" placeholder="請選擇活動區(qū)域">
<el-option label="區(qū)域一" value="shanghai"></el-option>
<el-option label="區(qū)域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<!--checkout多選框-->
<el-form-item label="活動性質(zhì)" prop="type">
<el-checkbox-group v-model="ruleForm.type">
<el-checkbox label="美食/餐廳線上活動" name="type"></el-checkbox>
<el-checkbox label="地推活動" name="type"></el-checkbox>
<el-checkbox label="線下主題活動" name="type"></el-checkbox>
<el-checkbox label="單純品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<!--redio單選框-->
<el-form-item label="特殊資源" prop="resource">
<el-radio-group v-model="ruleForm.resource">
<el-radio label="線上品牌商贊助"></el-radio>
<el-radio label="線下場地免費"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<script>
export default {
data() {
//手機號
var validatePhone = (rule, value, callback) => {
if (/^1[34578]{1}\d{9}$/.test(value) == false) {
callback(new Error("請輸入正確的手機號"));
} else {
callback();
}
};
return {
rules: {
name: [
{ required: true, message: '請輸入活動名稱', trigger: 'blur' },
{ min: 3, max: 5, message: '長度在 3 到 5 個字符', trigger: 'blur' }
],
region: [
{ required: true, message: '請選擇活動區(qū)域', trigger: 'change' }
],
type: [
{ type: 'array', required:true,message:'請選擇活動性質(zhì)', trigger: 'change' }
],
resource: [
{ required: true, message: '請選擇活動資源', trigger: 'change' }
],
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
完整代碼:
<template>
<div>
<p>shopInfo</p>
<div class="company" id="company">
<!-- model是驗證的數(shù)據(jù)來源 -->
<el-form :model="registData" :rules="rules" ref="registerRef" label-width="100px" class="demo-ruleForm">
<el-form-item label="活動名稱" prop="name">
<!-- validate-event輸入時不觸發(fā)表單驗證,提交時再驗證,也可以設(shè)置成動態(tài)驗證 -->
<el-input v-model="registData.name" :validate-event="false"></el-input>
</el-form-item>
<el-form-item label="區(qū)域面積" prop="area">
<!-- 輸入的類型為Number時,需要加一個數(shù)字轉(zhuǎn)換的修飾符,輸入框默認的類型是String類型,但是我試了一下,發(fā)現(xiàn)并不能做驗證,所以自己寫了函數(shù)方法驗證 -->
<!-- <el-input v-model.number="registData.area" autocomplete="off"></el-input> -->
<el-input v-model="registData.area" @keyup.native="InputNumber('area')" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="活動區(qū)域" prop="region">
<el-select v-model="registData.region.country" placeholder="請選擇國家">
<el-option label="國家一" value="USA"></el-option>
<el-option label="國家二" value="China"></el-option>
</el-select>
<el-select v-model="registData.region.city" placeholder="請選擇城市">
<el-option label="城市一" value="shanghai"></el-option>
<el-option label="城市二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活動時間" required>
<el-col :span="11">
<el-form-item prop="date1">
<el-date-picker type="date" placeholder="選擇日期" v-model="registData.date1" style="width: 100%;"></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-form-item prop="date2">
<el-time-picker type="fixed-time" placeholder="選擇時間" v-model="registData.date2" style="width: 100%;"></el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="即時配送" prop="delivery">
<el-switch v-model="registData.delivery"></el-switch>
</el-form-item>
<el-form-item label="活動性質(zhì)" prop="type">
<el-checkbox-group v-model="registData.type">
<el-checkbox label="美食/餐廳線上活動" name="type"></el-checkbox>
<el-checkbox label="地推活動" name="type"></el-checkbox>
<el-checkbox label="線下主題活動" name="type"></el-checkbox>
<el-checkbox label="單純品牌曝光" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊資源" prop="resource">
<el-radio-group v-model="registData.resource">
<el-radio label="線上品牌商贊助"></el-radio>
<el-radio label="線下場地免費"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活動圖片" prop="fileUrl">
<el-upload
:action="action"
:on-success="handleSuccess"
:data="uploadData"
:limit="20"
list-type="picture-card"
:on-preview="handlePreview"
:on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
<el-form-item label="活動形式" prop="desc">
<el-input type="textarea" v-model="registData.desc"></el-input>
</el-form-item>
<el-form-item>
<!-- 提交的時候傳入的是表單的ref -->
<el-button type="primary" @click="submitForm('registerRef')">立即創(chuàng)建</el-button>
<el-button @click="resetForm('registerRef')">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<style scoped>
.company {
padding: 30px;
text-align: left;
width: 600px;
}
</style>
<script>
export default {
name: 'shopInfo',
data () {
return {
registData: {
name: '', // 名稱
area: '', // 面積
region: {}, // 地區(qū)
date1: '', // 日期
date2: '', // 時間
delivery: false, // 即時配送
type: [], // 活動性質(zhì)
resource: '', // 特殊資源
fileUrl: '', // 活動圖片
desc: '' // 活動形式
}, // 需要驗證的表單屬性,必須在data中定義
rules: { // 表單驗證規(guī)則
name: [
{ required: true, message: '請輸入活動名稱' }, // 'blur'是鼠標失去焦點的時候會觸發(fā)驗證
{ min: 3, max: 5, message: '長度在 3 到 5 個字符' }
],
area: [
// 數(shù)字類型
// {type: 'number', message: '請輸入數(shù)字類型', trigger: 'blur'},
// {type: 'integer', message: '請輸入數(shù)字類型', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發(fā)驗證
{required: true, message: '請輸入?yún)^(qū)域面積', trigger: 'blur'}
],
region: [
{
type: 'object',
required: true,
trigger: 'change',
fields: {
country: {required: true, message: '請選擇國家', trigger: 'blur'},
city: {required: true, message: '請選擇城市', trigger: 'blur'}
}
}
],
date1: [
{ type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
],
date2: [
{ type: 'date', required: true, message: '請選擇時間', trigger: 'change' }
],
type: [
{ type: 'array', required: true, message: '請至少選擇一個活動性質(zhì)', trigger: 'change' }
],
resource: [
{ required: true, message: '請選擇活動資源', trigger: 'change' }
],
fileUrl: [
{ required: true, message: '請上傳圖片', trigger: 'change' }
],
desc: [
{ required: true, message: '請?zhí)顚懟顒有问?, trigger: 'blur' }
]
},
action: `https://xxx.com`,
uploadData: {userId: 1304, pathName: 'company'}
}
},
methods: {
// 過濾輸入的金額
InputNumber (property) {
this.registData[property] = this.limitInputPointNumber(this.registData[property])
},
// 驗證只能輸入數(shù)字
limitInputNumber (val) {
if (val) {
return String(val).replace(/\D/g, '')
}
return val
},
// 限制只能輸入數(shù)字(可以輸入兩位小數(shù))
limitInputPointNumber (val) {
if (val === 0 || val === '0' || val === '') {
return ''
} else {
let value = null
value = String(val).replace(/[^\d.]/g, '') // 清除“數(shù)字”和“.”以外的字符
value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多余的
value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數(shù)
return Number(value)
}
}
}