Vue脚手架系列10-表单组件设计-Form组件检验方法完结

121 阅读1分钟

Vue脚手架系列10-表单组件设计-Form组件检验方法完结

1.FormItem:

🤖思路:

  • Input组件中的内容,在FromItemvalidate方法进行校验,校验的结果通过promise返回回去
  • FormItem组件的生命周期中的mounted中,通过this.$parent.$emit('formItemAdd', this);调用FormComponent中的'formItemAdd'.
<template>
<div>
    <!--如果有label显示,没有就隐藏 -->
    <label v-if="label">{{label}}</label>
    <!-- 插槽,用于放input组件的-->
    <slot></slot>
    <!-- 显示校验的错误信息-->
    <p v-if="validateStatus==='error'" class="error">{{errorMessage}}</p>
</div>
</template>

<script>
//绑定label和prop属性
//获取当前输入框的规则
//如果输入框和ruler不匹配,显示错误信息
//input组件中,用户输入内容的时候,通知formItem的做校验(校验的方法)
//使用async-validate做校验

//npm i async-validator -S 安装
import Schema from 'async-validator';
export default {
    data() {
        return {
            validateStatus: '', //校验的状态值
            errorMessage: '', //显示的错误信息
        };
    },
    inject: ['form'],
    props: {
        label: {
            type: String,
            default: '',
        },
        prop: {
            //这个prop指的是age或者pass
            type: String,
            default: '',
        },
    },
    //这里涉及一个生命周期的调用,子组件挂载完毕之后,再去走父组件的created方法
    created() {
        this.$on('validate', this.validate);
    },
    mounted() {
        //这里必须做判断,因为FormComponent组件的子组件,不一定是FormItem
        if (this.prop) {
            this.$parent.$emit('formItemAdd', this);
        }
    },
    methods: {
        validate(value) {
            //当前的value是输入框的值
            console.log('我是输入框输入的值', value);
            console.log('我是provide的form实例上的规则rules', this.form.rules);
            console.log('我是prop', this.prop);
          
            //🍊这里修改之前的部分,因为要使用Promise.all的方法去处理所有的tasks
            return new Promise((resolve) => {
                //下面开始进入校验的逻辑了
                //此对象要存储校验规则这个校验规则(实际上是从Form组件中拿到的)
                //让descriptor变成动态的值
                // let descriptor = {};
                // descriptor[this.prop] = this.form.rules[this.prop];
                const descriptor = {
                    [this.prop]: this.form.rules[this.prop]
                };
                const validator = new Schema(descriptor);
                // let obj = {};
                // obj[this.prop] = value;
                const obj = {
                    [this.prop]: value
                };
              
                validator.validate(obj, (errors) => {
                    if (errors) {
                        //显示你的错误
                        this.validateStatus = 'error';
                        this.errorMessage = errors[0].message;
                        resolve(false);
                    } else {
                        //没错误就将错误消息置空
                        this.validateStatus = '';
                        this.errorMessage = '';
                        resolve(true);
                    }
                });
            });
        },
    },
};
</script>

<style scoped>
.error {
    color: red;
}
</style>

2.FormComponent组件:

🤖思路:

  • FormComponent组件中的created生命周期中,绑定formItemAdd,将每个FormItem校验项目(promise对象),pushfiled数组中,filed中的每个子项都是一个promise对象。(当子组件FormItem加载完毕后,这里在created中进行一个接收,🤔就是由内而外的感觉,你懂的...)

  • FormComponent组件中的validate方法,是在下面的Form组件中被调用的。

  • validate方法中通过Promise.all方法去验证每一个子项的,然后将结果的布尔值作为参数传给callback函数。

<template>
<div>
    <!--插槽--用来包裹的FormItem等-->
    <slot></slot>
</div>
</template>

<script>
export default {
    //🌵通过provide将自己的实例传递给内层的FormItem,这样不管中间间隔了div或者其他元素,都可以获得rules
    provide() {
        return {
            form: this,
        };
    },
    //🌵当子组件FormItem加载完毕后,这里在created中进行一个接收
    created() {
        //🍊缓存需要校验的表单项目
        this.fileds = [];
        this.$on('formItemAdd', (item) => {
            this.fileds.push(item);
        });
    },
    props: {
        model: {
            type: Object,
            required: true,
        },
        rules: {
            type: Object,
        },
    },
    methods: {
        //🍊这里这里
        validate(callback) {
            //这里的tasks数组中,保存着多个输入验证之后的promise对象
            const tasks = this.fileds.map((item) => item.validate());
            let ret = true;
            Promise.all(tasks).then((results) => {
                //这里是每个task调用完事的结果组成的数组
                console.log('我是PromiseAll的结果results', results);
                //对结果数组results进行
                results.forEach((valid) => {
                    if (!valid) {
                        ret = false;
                    }
                });
                //这个callback就是Form组件中调用时传递的
                callback(ret);
            });
        },
    },
};
</script>

<style scoped>
</style>

3.Form组件:

<template>
<div>
    <!--这是我们自己的input组件-->
    {{ruleForm}}
    <m-form :model="ruleForm" :rules="rules" ref="rulebox">
        <m-form-item label="用户名" prop="name">
            <m-input v-model="ruleForm.name"></m-input>
        </m-form-item>
        <m-form-item label="年龄" prop="age">
            <m-input type="age" v-model="ruleForm.age"></m-input>
        </m-form-item>
        <m-form-item lable="密码" prop="pass">
            <m-input type="password" v-model="ruleForm.pass"></m-input>
        </m-form-item>
        <!--这里新加了按钮用于最后的提交-->
        <m-form-item>
            <el-button type="primary" @click="submitForm('rulebox')">提 交</el-button>
        </m-form-item>
    </m-form>
</div>
</template>

<script>
import MInput from './Input';
import MFormItem from './FormItem';
import MForm from './FormComponent';
export default {
    components: {
        MInput,
        MFormItem,
        MForm,
    },
    data() {
        return {
            ruleForm: {
                pass: '98',
                age: '18',
                name: '索隆',
            },
            rules: {
                name: [{
                        required: true,
                        message: '请输入名字',
                    },
                    {
                        min: 2,
                        max: 4,
                        message: '请输入2~4位用户名',
                    },
                ],
                pass: [{
                        require: true,
                        message: '请输入密码',
                    },
                    {
                        min: 6,
                        max: 10,
                        message: '请输入6~10密码',
                    },
                ],
                age: [{
                    require: true,
                    message: '请输入年龄',
                }, ],
            },
        };
    },
    methods: {
        submitForm(name) {
            console.log(name);
            console.log('我是validate的refs[name]', this.$refs);
            //这里拿到的是FormComponent组件的实例去调用他的validate方法
            this.$refs[name].validate((valid) => {
                console.log('我是validate', valid);
                if (valid) {
                    alert('哎呦不错哦,通过验证了');
                } else {
                    alert('请仔细检查您的提交内容');
                }
            });
        },
    },
};
</script>