組件 vantForm.vue
<template>
<div>
<slot name="items"></slot>
</div>
</template>
<script>
/**
* author:ronggang
* email:[email protected]
*/
export default {
name: 'vant-form',
data() {
return {
rulesEles: []
}
},
props: ['inputVail', 'rules'],
mounted() {
// 遞歸獲取所有帶有 rule 屬性的元素
this.rulesEles = this.getRuleEle(this.$slots.items);
// 處理 輸入監聽的校驗
if (this.inputVail) this.eleSetInput();
},
methods: {
// 遞歸獲取插槽內所有擁有 input 屬性的元素【內部方法】
getRuleEle(eleObj) {
let self = this, childs = [];
if (!eleObj) return;
// 循環所有元素(兼容 對象和數組的情況)
for (let i in eleObj instanceof Array ? eleObj : [eleObj]) {
let ele = eleObj[i];
// 當前元素包含 rule 屬性,則收錄起來
if (ele.data && ele.data.attrs['rule']) {
ele.elm.getElementsByClassName('van-field__error-message')[0].style.display = 'none';
childs.push(ele);
}
// 當前元素存在子元素,則遞歸查詢
ele.children && childs.push.apply(childs, this.getRuleEle(ele.children));
}
return childs;
},
// 設置 需要校驗的屬性 的 input監聽 校驗 【內部方法】
eleSetInput() {
let self = this;
try {
for (let i in self.rulesEles) {
(function (index) {
// 獲取元素下 input 元素(目前只針對 單個輸入框做處理)
let inputEle = self.rulesEles[index].elm.getElementsByTagName('input')[0];
inputEle.oninput = function () {
// 輸入實時校驗
self.handleVail(index);
}
})(i);
}
} catch (e) {
console.error('vail error:' + e);
}
},
// 檢驗元素的值是否滿足條件(參數:索引值 )【內部方法】
handleVail(i) {
try {
let self = this, handleEle = self.rulesEles[i];
// 獲取元素下 input 元素(目前只針對 單個輸入框做處理)
let inputValue = handleEle.elm.getElementsByTagName('input')[0].value, vailFlag = true;
// 獲取設置的校驗規則
let ruleObj = self.rules ? self.rules[handleEle.data.attrs['rule']] : null;
if (!ruleObj) return vailFlag;
// 非空校驗
vailFlag = ruleObj.required ? !!inputValue : vailFlag;
// 正則校驗
vailFlag = ruleObj.regExp ? ruleObj.regExp.test(inputValue) && vailFlag : vailFlag;
// 用戶自定義校驗
vailFlag = typeof ruleObj.handleVailFun === 'function' ? ruleObj.handleVailFun(inputValue) && vailFlag : vailFlag;
console.log(handleEle);
// 獲取組件實例,修改錯誤信息(註釋的代碼可以實現效果,但是違反了子組件修改父組件的規則)
// handleEle.componentInstance.errorMessage = vailFlag?'':ruleObj.errorMessage;
//目前是通過控制元素顯示隱藏去實現錯誤信息的展示
if (!vailFlag) self.rulesEles[i].elm.getElementsByClassName('van-field__error-message')[0].style.display = 'block';
else self.rulesEles[i].elm.getElementsByClassName('van-field__error-message')[0].style.display = 'none';
return vailFlag;
} catch (e) {
console.error('vail error:' + e);
}
},
// 整體校驗【對外提供方法】
allVail() {
let self = this, vailFlag = true;
for (let i in this.rulesEles) {
vailFlag = !self.handleVail(i) ? false : vailFlag && true;
}
return vailFlag;
}
}
}
</script>
<style>
</style>
使用
<template>
<div class="form-container">
<van-nav-bar title="表單校驗擴展組件" left-text="返回" left-arrow
@click-left="back" />
<vantForm ref="vanForm" :rules="rules" inputVail="true">
<template slot="items">
<van-field error-message="請輸入正確的用戶名~" rule="userName"
label="用戶名" placeholder="請輸入用戶名" v-model="reqParam.userName"/>
<van-field error-message="請輸入正確的手機號~" rule="phone"
label="手機號碼" placeholder="請輸入手機號碼" v-model="reqParam.phone"/>
<van-field error-message="請輸入6~20位密碼~" rule="pwd"
type="password" label="密碼" placeholder="請輸入密碼" v-model="reqParam.pwd"/>
<van-field error-message="兩次輸入密碼不一致~" rule="confirmPwd"
type="password" label="再次輸入" placeholder="再次輸入" v-model="reqParam.confirmPwd" />
</template>
</vantForm>
<van-button class="submit-btn" type="primary" @click="submitForm">提交</van-button>
</div>
</template>
<script>
import VantForm from '../components/vantForm';
// import { Toast } from 'vant';
export default {
name: 'formVail',
data() {
return {
reqParam: {
userName: '',
phone: '',
pwd: '',
confirmPwd: ''
},
rules: {
'userName': {required: true},
'phone': {regExp: /^(1\d{10})$/, required: true},
'pwd': { regExp: /^(\w){6,20}$/, required: true},
'confirmPwd': { required: true
,handleVailFun:val => { return val === this.reqParam.pwd; }
}
}
}
},
created() {
},
methods: {
back() {
this.$router.back();
},
submitForm() {
this.$refs['vanForm'].allVail()?Toast.success('校驗通過'): Toast.fail('提交失敗');
}
},
components: {
VantForm
}
}
</script>
<style scoped lang="less">
.form-container{
.submit-btn{
width:100%;
}
}
</style>
效果預覽