微信小程序

vue表单组件的实现

vue表单组件的实现

组件化常用技术

表单组件的实现

input

双向绑定:@input、:value

派发校验事件

<template>
    <div>
        <input :value="value" @input="onInput" v-bind="$attrs">
    </div>
</template>
<script>
    export default {
        inheritAttrs: false,
        props: {
            value: {
                type: String,
                default: ""
            }
        },
        methods: {
            onInput(e) {
                this.$emit("input", e.target.value);
                this.$parent.$emit('validate');
            }
        }
    };
</script>

FormItem

给Input预留插槽 - slot

能够展示label和校验信息

能够进行校验

<template>
    <div><label v-if="label">{{label}}</label>
        <slot></slot>
        <p v-if="errorMessage">{{errorMessage}}</p></div>
</template>
<script> import Schema from 'async-validator'

export default {
    inject: ["form"],
    props: {label: {type: String, default: ""}, prop: {type: String}},
    data() {
        return {errorMessage: ""};
    },
    mounted() {
        this.$on('validate', () => {
            this.validate()
        })
    },
    methods: {
        validate() {
            // 做校验 
            const value = this.form.model[this.prop]
            const rules = this.form.rules[this.prop]
            // npm i async-validator -S 
            const desc = {[this.prop]: rules};
            const schema = new Schema(desc);
            // return的是校验结果的Promise 
            return schema.validate({[this.prop]: value}, errors => {
                if (errors) {
                    this.errorMessage = errors[0].message;
                } else {
                    this.errorMessage = ''
                }
            })
        }
    },
};</script>

Form

给FormItem留插槽

设置数据和校验规则

全局校验

<template>
    <div>
        <slot></slot>
    </div>
</template>
<script> export default {
    provide() {
        return {form: this};
    }, props: {model: {type: Object, required: true}, rules: {type: Object}}, methods: {
        validate(cb) {
            const tasks = this.$children.filter(item => item.prop).map(item => item.validate());
            Promise.all(tasks).then(() => cb(true)).catch(() => cb(false));
        }
    }
};</script>

目标

  1. 能手写Form、FormItem、Input实现
  2. 尝试解决Input里面$parent派发事件不够健壮的问题
  3. 说出.sync和v-model的异同

最近文章: