vue 表單校驗(二)
vue element-ui表單校驗
由於現在使用element-ui
進行form表單校驗,因而使用其自帶的校驗規則進行校驗,發現有些並不是那么好校驗,或者說是校驗起來很繁瑣,因而一直在研究中
表單校驗分類
前后端校驗
- 前端校驗
- 后端校驗
這種目前一般是結合起來使用,很少單純前端校驗,或者單純后端校驗的
前端檢驗
- 數據錄入時校驗
- 數據回顯時校驗
- 動態創建時校驗
- 數據是否必填時校驗
接下來所談論的校驗都是基於前端進行校驗,若是后天校驗,只是統一校驗規則而已,這樣前后便可以統一了。其實這里並不是很簡單,但是不得不細心,而已最好,前后台都要其校驗規則,以及校驗話術放在一個公共的地方,避免在每個具體文件內進行修改。若是能更好的話,類似 google email 那樣,通過后台返回規則類型,以及對應前台的具體編號,進行顯示即可(比如1: 不能為空, 2:校驗規則不合...) 這樣的好處,前台只認這個數字即可,不然后台返回什么,前台出什么錯誤,都是統一顯示(這個扯遠了),講今天的重點
基於 element-ui
自帶的 表單校驗
- 數據錄入時校驗
element-ui form validate
el-form
標簽- 屬性
- model 對象卻只能是一維 { a: 1, b: 2 }, 不能是 { a: { b: 2 } }, 不然關聯不到
- rules 按照規則要求即可
- ref 提交表單時觸發
- 屬性
el-form-item
標簽 必須使用這個進行包裹 表單框... 校驗才會有效- 屬性
- prop 只有標識了這個才會進入校驗
- 屬性
<template>
<el-form
:model="ruleForm"
ref="ruleForm"
label-width="100px"
:rules="rules">
<el-form-item
label="活動名稱"
prop="name">
<el-input v-model="ruleForm.name"></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
@click="submitForm('ruleForm')">立即創建</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
...
data () {
const isNum = (rule, value, callback) => { // 參數順序必須如
let reg = /^[0-9]{5,20}$/;
if (reg.test(value)) {
callback()
} else {
callback(new Error("不是數據"))
}
}
return {
ruleForm: {
name: ''
},
rules: {
name: [
{
required: true, // 用來設置是否必填
message: '不能為空', // 錯誤信息展示
trigger: 'blur' // 觸發校驗事件
},
{
min: 3,
max: 5,
message: '長度在 3 到 5 個字符',
trigger: 'blur'
},
{
validator: isNum, // 自定義校驗
trigger: ['blur', 'change'] // 填寫 blur change時,可以達到類似 input事件,實時進行校驗
}
]
}
}
},
methods: {
/**
* 表單提交
*/
submitFomr (formName) {
this.$refs[formName].validate(valid => {
if (valid) {
alert('success')
} else {
alert('error')
}
})
},
/**
* 重置表單
*/
resetForm (formName) {
this.$refs[formName].resetFields()
}
}
</script>
以上是一個正常表單的大致模型
- 數據回顯時校驗
主要是數據返回時,要不要觸發校驗
- 不觸發 github 這里有一些解釋,不是很好弄
- 觸發 (跟產品溝通過,傾向於這種)
當前基於數據反顯時就觸發校驗
setFormData () {
setTimeout(() => {
this.ruleForm = {
name: '測試項目',
region: 2,
type: [1, 2],
resource: 1,
desc: '測試數據回顯時校驗顏色變化問題'
}
this.$nextTick(() => {
// 為了回顯時,不只是el-select 校驗被觸發
this.$refs.ruleForm.validate()
})
}, 1500)
- 動態創建時校驗
有時候需要動態創建一個輸入框時,也需要檢驗,這時候就需要動態校驗,不然一直卡着過不去
<el-row
class="sc-row"
:gutter="20"
v-for="(t, i) in ruleForm.contactList"
:key="t.id">
<!-- :key="i" 沒問題; :key="t.id" 時,不會變亮 ==== 沒必要在第一次賦值時給id,新增時再給即可-->
<el-col :span="8">
<el-form-item
label="姓氏"
:prop="'contactList.' + i +'.family_name'"
:rules="[
{ required: true, message: '不能為空', trigger: ['blur', 'change']}
]">
<el-input v-model="t.family_name"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="名字"
:prop="'contactList.' + i +'.contact_name'"
:rules="[
{required: true, message: '不能為空', trigger: ['blur', 'change']}
]">
<el-input v-model="t.contact_name"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-button @click.prevent="deleteConcats(t)">刪除</el-button>
</el-col>
</el-row>
重點,切記切記
-
循環
v-for
==v-for = '(item, i) in list' :key="item.id"
i -
el-form-item
屬性:prop = "
contactList.${i}.contact_name"
:rules="[{{required: true, message: '不能為空', trigger: ['blur', 'change']}]"
寫相應的校驗規則
-
刪除已添加的表單
- v-for 綁定時,
:key="item.id"
使用對應值的id
,而不是對應的索引i
addConcats () { this.ruleForm.contactList.push({ family_name: '', contact_name: '', id: Date.now() // 還是需要使用,這樣可以 避免校驗觸發時,刪除后卻沒有變化 }) }, deleteConcats (item) { const List = this.ruleForm.contactList const index = List.findIndex((val) => { return item === val }) List.splice(index, 1) } }
- v-for 綁定時,
-
數據是否必填時校驗
<el-form-item
label="是不是必填"
prop="isRequire"
:rules="[
{required: isRequire, message: '請填寫', trigger: 'blur'}
]">
<el-input v-model="ruleForm.isRequire"></el-input>
</el-form-item>
是否選填,個人建議直接以動態form表單形式進行展示,這樣便可以通過
{ reuired: isRequire }
,isRequire
Boolean類型
總結
至此,大致的form表單校驗就差不多了,雖然看起來很簡單,但是也是我不斷采坑過來的,在此,我更加推薦使用 element-ui-verify,里面有詳細的文檔,多多關注即可
- 當前校驗的缺點
- 動態創建
<el-row class="sc-row" :gutter="20" v-for="(t, i) in ruleForm.contactList" :key="t.id"> <el-col :span="8"> <el-form-item label="姓氏" :prop="'contactList.' + i +'.family_name'" :rules="[ { required: true, message: '不能為空', trigger: ['blur', 'change']} ]"> <el-input v-model="t.family_name"></el-input> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="名字" :prop="'contactList.' + i +'.contact_name'" :rules="[ {required: true, message: '不能為空', trigger: ['blur', 'change']} ]"> <el-input v-model="t.contact_name"></el-input> </el-form-item> </el-col> <el-col :span="8"> <el-button @click.prevent="deleteConcats(t)">刪除</el-button> </el-col> </el-row>
上面的 姓氏和名字 同為中文或英文時,很難進行判斷 element密碼兩次是否相同,但是當前動態創建時,無法傳遞
索引
,自定義方法中無法進行傳參,導致拿不到同一索引下的姓氏跟名字,也就無法進行匹配判斷了 - 其他注意細節
- 在自定義驗證里面每一個判斷都要有
callback()
,就是要保證callback()
一定會執行到,不然既不報錯,也不提交代碼,令人很是無語 - async-validator
- 上面例子的code
- 在自定義驗證里面每一個判斷都要有
到此,算是一個給自己年末去心病吧,這個困惑我太久了,到現在想想都恐怖,算是簡單補充下吧,后期再多多注意
在此拋出幾個問題,留給自己思考
- 大型表單時,哪兒錯誤,自動定位到哪兒,同時
focus
- 統一錯誤信息,后台傳給前台具體id,以供前台進行錯誤信息展示,這個前台統一管理
- 考慮使用其他校驗插件,多多擴充自己的腦容量