<template>
<div>
<slot name="items"></slot>
</div>
</template>
<script>
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 && ele.data.attrs['rule']) {
// console.log('getElementsByClassName ',ele.elm.getElementsByClassName('van-field__error-message'))
const element = ele.elm.getElementsByClassName('van-field__error-message')
if(element && element.length > 0){
element[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];
let textareaEle = self.rulesEles[index].elm.getElementsByTagName('textarea')[0]
let editEle
if(inputEle){
editEle = inputEle
}else if(textareaEle){
editEle = textareaEle
}
if(editEle){
editEle.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 vailFlag = true
let input = handleEle.elm.getElementsByTagName('input')[0]
let textArea = handleEle.elm.getElementsByTagName('textarea')[0]
let inputValue = ''
if(input){
inputValue = input.value
}else if (textArea)(
inputValue = textArea.value
)
// 获取设置的校验规则
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="sealDraftForm" >
<vant-form ref="sealDraftForm" :rules="rules" inputVail='true'>
<template slot="items">
<van-field error-message="请输入正确的编号" rule="serialNumber" label="编号" placeholder="" readonly
v-model="formData.serialNumber"/>
<van-field error-message="请输入用印名称" rule="sealName" label="用印名称" placeholder="请输入"
:value="sealName" readonly clickable @click="selectSealName"/>
<van-field error-message="请输入申请部门" rule="deptName" label="申请部门" placeholder="请输入"
v-model="formData.deptName"/>
<van-field error-message="请输入申请事由" rule='reason' label="申请事由" placeholder="请输入内容,限100字以内"
v-model="formData.reason" class="marginTop10" type="textarea" rows="1" autosize
maxlength="100" show-word-limit/>
<van-field error-message="请输入用印内容" rule='sealContent' label="用印内容" placeholder="请输入内容,限200字以内"
v-model="formData.sealContent" class="marginTop10" type="textarea" rows="1" autosize
maxlength="200" show-word-limit/>
<van-field error-message="请输入用印数量" rule='sealNumber' label="用印数量" placeholder="请输入" type="digit"
v-model="formData.sealNumber" class="marginTop10"/>
<van-field error-message="请输入部门领导意见" rule='deptLeader' label="部门领导" placeholder="" readonly>
<template #input>
</template>
</van-field>
<van-field error-message="请输入党工委、管委会领导" rule='mangerLeader' label="党工委、管委会领导"
placeholder="" class="marginTop10" readonly>
<template #input>
</template>
</van-field>
<van-field error-message="请输入经办人" rule="createUserName" label="经办人" placeholder="请输入" v-model="formData.createUserName" />
<van-field error-message="请输入用印时间" rule='completeTime' label="用印时间" placeholder="请输入" readonly clickable
:value="formData.completeTime" @click="datePicker('completeTime')"/>
<van-field label="附件" v-if="attachments && attachments.length > 0">
<template #input>
<div style="margin-bottom: 10px;border-bottom: 1px solid #f4f4fb;color: #5EB7FD;width: 100%;"
@click="previewFile(attachment.attachmentDTO)"
v-for="(attachment,index) in attachments" :key="index">
{{attachment.attachmentDTO.fileName}}
</div>
</template>
</van-field>
<van-popup v-model="showPicker" position="bottom" round>
<van-datetime-picker
v-model="currentDate"
type="date"
@confirm="onConfirm"
@cancel="showPicker = false"
/>
</van-popup>
<van-action-sheet round v-model="showActionSheet" :actions="sealNameActions" @select="onSelect" />
</template>
</vant-form>
<footer class="bottom">
<van-button round type="info" size="small" @click="submitForm('2')" class="marginBtn">
保存并发送
</van-button>
</footer>
</div>
</template>
参考自: https://blog.csdn.net/u012724239/article/details/100557499