Vant-ui实现表单校验组件

<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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值