element-ui Form表單驗證規則全解
阿新 • • 發佈:2018-12-24
element的form表單非常好用,自帶了驗證規則,用起來很方便,官網給的案例對於一些普通場景完全沒問題,不過一些複雜場景的驗證還得自己多看文件摸索,自己經過數次爬坑
之後,總結了幾種form表單的驗證規則,為了便於閱讀,驗證規則是拆分的,完整的程式碼放在文末
1. 普通輸入驗證
<el-form-item label="活動名稱" prop="name"> <!-- validate-event屬性的作用是: 輸入時不觸發表單驗證.提交時再驗證,你也可以設定成動態驗證 --> <el-input v-model="registData.name" :validate-event="false"></el-input> </el-form-item> rules: { // 表單驗證規則 name: [ { required:true, message: '請輸入活動名稱' }, // 'blur'是滑鼠失去焦點的時候會觸發驗證 { min: 3, max: 5, message: '長度在 3 到 5 個字元' } ] }
2. 數字型別驗證
<el-form-item label="區域面積" prop="area"> <!-- 輸入的型別為Number時,需要加一個數字轉換的修飾符,輸入框預設的型別是String型別,但是我試了一下,發現並不能做驗證,所以自己寫了函式方法驗證 --> <!-- <el-input v-model.number="registData.area" autocomplete="off"></el-input> --> <!-- keyup是滑鼠彈起事件, autocomplete是input自帶的原生屬性,自動補全功能,on為開啟,off為關閉 --> <el-input v-model="registData.area" @keyup.native="InputNumber('area')" autocomplete="off"></el-input> </el-form-item> area: [// 數字型別 'number', 整數: 'integer', 浮點數: 'float' // {type: 'number', message: '請輸入數字型別', trigger: 'blur'}, // {type: 'integer', message: '請輸入數字型別', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發驗證 {required: true, message: '請輸入區域面積', trigger: 'blur'} ], // 自己寫的正則驗證,限制使用者輸入數字以外的字元 // 過濾輸入的金額InputNumber (property) { this.registData[property] = this.limitInputPointNumber(this.registData[property]) }, // 驗證只能輸入數字 limitInputNumber (val) { if (val) { return String(val).replace(/\D/g, '') } return val }, // 限制只能輸入數字(可以輸入兩位小數) limitInputPointNumber (val) { if (val === 0 || val === '0' || val === '') { return '' } else { let value = null value = String(val).replace(/[^\d.]/g, '') // 清除“數字”和“.”以外的字元 value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多餘的 value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.') value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數 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 巢狀驗證(聯動驗證) 這種是聯動驗證,適用省級聯動場景,先選國家後觸發城市驗證
<!-- region是一個物件,國家和城市是它的屬性 --> <el-form-item label="活動區域" 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', // 官網提供了物件的巢狀驗證,只需要把需要驗證的屬性,放在fields物件裡,就會按順序進行驗證 fields: { country: {required: true, message: '請選擇國家', trigger: 'blur'}, city: {required: true, message: '請選擇城市', trigger: 'blur'} } } ],
4. 圖片上傳驗證(手動觸發部分驗證方法) 有時候會需要在表單裡上傳圖片,但是圖片上傳是一個非同步過程,屬性值改變後不會去觸發驗證規則
<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 = '' // 檔案刪除後也要觸發驗證,validateField是觸發部分驗證的方法,引數是prop設定的值 this.$refs.registerRef.validateField('fileUrl') }, // 圖片上傳 handleSuccess (res, file, fileList) { // 這裡可以寫檔案上傳成功後的處理,但是一定要記得給fileUrl賦值 this.registData.fileUrl = 'fileUrl' // 檔案上傳後不會觸發form表單的驗證,要手動新增驗證 this.$refs.registerRef.validateField('fileUrl') },
完整的程式碼
<template> <div> <p>shopInfo</p> <div class="company" id="company"> <!-- model是驗證的資料來源 --> <el-form :model="registData" :rules="rules" ref="registerRef" label-width="100px" class="demo-ruleForm"> <el-form-item label="活動名稱" prop="name"> <!-- validate-event輸入時不觸發表單驗證,提交時再驗證,也可以設定成動態驗證 --> <el-input v-model="registData.name" :validate-event="false"></el-input> </el-form-item> <el-form-item label="區域面積" prop="area"> <!-- 輸入的型別為Number時,需要加一個數字轉換的修飾符,輸入框預設的型別是String型別,但是我試了一下,發現並不能做驗證,所以自己寫了函式方法驗證 --> <!-- <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="活動區域" 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="活動性質" 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')">立即建立</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: {}, // 地區 date1: '', // 日期 date2: '', // 時間 delivery: false, // 即時配送 type: [], // 活動性質 resource: '', // 特殊資源 fileUrl: '', // 活動圖片 desc: '' // 活動形式 }, // 需要驗證的表單屬性,必須在data中定義 rules: { // 表單驗證規則 name: [ { required: true, message: '請輸入活動名稱' }, // 'blur'是滑鼠失去焦點的時候會觸發驗證 { min: 3, max: 5, message: '長度在 3 到 5 個字元' } ], area: [ // 數字型別 // {type: 'number', message: '請輸入數字型別', trigger: 'blur'}, // {type: 'integer', message: '請輸入數字型別', trigger: 'change'}, // 'change'是表單的值改變的時候會觸發驗證 {required: true, message: '請輸入區域面積', trigger: 'blur'} ], 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', 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: '請至少選擇一個活動性質', trigger: 'change' } ], resource: [ { required: true, message: '請選擇活動資源', trigger: 'change' } ], fileUrl: [ { required: true, message: '請上傳圖片', trigger: 'change' } ], desc: [ { required: true, message: '請填寫活動形式', trigger: 'blur' } ] }, action: `https://jsonplaceholder.typicode.com/posts/`, uploadData: {userId: 1304, pathName: 'company'} } }, created () { }, methods: { // 過濾輸入的金額 InputNumber (property) { this.registData[property] = this.limitInputPointNumber(this.registData[property]) }, // 驗證只能輸入數字 limitInputNumber (val) { if (val) { return String(val).replace(/\D/g, '') } return val }, // 限制只能輸入數字(可以輸入兩位小數) limitInputPointNumber (val) { if (val === 0 || val === '0' || val === '') { return '' } else { let value = null value = String(val).replace(/[^\d.]/g, '') // 清除“數字”和“.”以外的字元 value = value.replace(/\.{2,}/g, '.') // 只保留第一個. 清除多餘的 value = value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.') value = value.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能輸入兩個小數 return Number(value) } }, // 預覽圖片 handlePreview (file) { }, // 刪除圖片 handleRemove (file, fileList) { this.registData.fileUrl = '' // 檔案刪除後也要觸發驗證,validateField是觸發部分驗證的方法,引數是prop設定的值 this.$refs.registerRef.validateField('fileUrl') }, // 圖片上傳 handleSuccess (res, file, fileList) { // 這裡可以寫檔案上傳成功後的處理,但是一定要記得給fileUrl賦值 this.registData.fileUrl = 'fileUrl' // 檔案上傳後不會觸發form表單的驗證,要手動新增驗證 this.$refs.registerRef.validateField('fileUrl') }, submitForm (formName) { console.log(this.registData) this.$refs[formName].validate((valid) => { if (valid) { alert('submit!') } else { console.log('error submit!!') return false } }) }, resetForm (formName) { this.$refs[formName].resetFields() } } }