vue component-based development actual combat - ElementUI achieve simple form components of Form

Input Components

Features:

  • Data double bind
  • Notice FormItem component check
<template>
  <div>
     <input  :type="type" :value="value" @input="onInput" v-bind="$attrs" >
  </div>
</template>
<script>
export default {
    inheritAttrs:false,
    props:{
        value:{
            type: String,
            default: ''
        },
        type:{
            type: String,
            default: 'text'
        },  
    },
    methods:{
        onInput(e){
            this.$emit('input',e.target.value);
            // 让父组件自己派发自己监听该valid事件进行校验。 
            this.$parent.$emit('valid');
        }
    }
}
</script>

$attrsAnd v-bind="$attrs"use

  • $attrsVue built-in properties is used to store the external transfer but was not received props to a component property.
  • These attributes have non-prop characteristics :
    1 will be automatically added to the root element assembly.
    2. By default, the characteristic properties of non-prop will overwrite the contents of the same name of the root element assembly. For styleand classhave special handling: merge (but if it is the style of the same name will be overwritten)
    3. If you do not want to inherit the root element of non prop assembly features, you can configure the component configuration items inheritAttrs:false(API has no effect on the style and class)

v-bind="$attrs"It is $attrsa method of deconstruction assignment, deconstruct :key="value"form.

FormItem components

Features:

  • check
  • label display
  • Error display
<template>
  <div>
    <label v-if="label">{{label}}</label>
    <slot></slot>      
    <p v-if="error">{{error}}</p>
  </div>
</template>
<script>
  import Schema from 'async-validator'; // 校验包
  export default {
    inject:['form'],
    props:{
      label:{
        type:String,
        default:''
      },
      prop:{
        type:String,
        default:''
      }
    },
    data(){
      return {
        error:''
      }
    },
    mounted(){
      this.$on('valid',()=>{
          this.validate();
      })
    },
    methods:{
      validate(){
        const rules = this.form.rules[this.prop];
        const value = this.form.model[this.prop];

        const schema = new Schema({[this.prop]:rules});
        // 返回Promise<Boolean>
        return schema.validate({[this.prop]:value},(errors)=>{
          if(errors){
            this.error = errors[0].message;
          }else{
            this.error = '';
          }
        })
      }
    }
  }
</script>   

Form Components

Features:

  • Provide value
<template>
    <div>
        <slot></slot>
    </div>
</template>
<script>
export default {
    provide(){
        return {
            form:this  // 把form组件实例传给后代,后代可以通过该实例访问该组件上的属性 model、rule ...
        }
    },
    props:{
        model:{
            type:Object,
            reuqired:true
        },
        rules:{
            type:Object,
        }
    },
    methods:{
        validate(cb){
            const checkRes = this.$children
            .filter(item => item.prop)
            .map(item => item.validate());

            Promise.all(checkRes)
            .then(()=>cb(true))
            .catch(()=>cb(false));
        }
    }
}
</script>

Universal library development and inter-level commonly used method of mass participation provide / inject

  1. Ancestor has set provideconfiguration items, similar to the datausage, but its data is used to future generations, not for my own use.
  2. Offspring by injectacquiring data progenitor provide configuration items.

        inject: ['form'] // 祖代provide中的key值

    The introduction of third-party libraries can be avoided by the way, such as vuex, if not deep level need to propsapproach cumbersome transfer.

use

<template>
    <div>
        <Form :model="model" :rules="rules" ref="myform">
            <FormItem label="用户名" prop="username">
                <Input v-model="model.username" placeholder="输入用户名" @ev="func" />
            </FormItem>
            <FormItem label="密码" prop="password" >
                <Input v-model="model.password" placeholder="输入密码" type="password" @ev="func" />
            </FormItem>
             <FormItem >
                 <button @click="submitForm('myform')">提交</button>
            </FormItem>
        </Form>
    </div>
</template>
<script>
import Input from '@/components/form/Input'; 
import Form from '@/components/form/Form'; 
import FormItem from '@/components/form/FormItem';
export default {
    components:{
        Input,
        Form,
        FormItem
    },
    data(){
        return{
            model:{
                username:'',
                password:'',
            },
            rules:{
                username:[{required:true,message:'用户名必填'}],            
                password:[{required:true,message:'密码必填'}],
            },
        }
    },
    methods:{
        submitForm(form){
            this.$refs[form].validate(valid=>{
                if(valid){
                    alert('校验通过');
                }else{
                    alert('校验失败');
                }
            })
        }
    }
}
</script> 

conclusion of issue

  1. Why is the data model model on the form?
    In order to facilitate verification, validation within FormItem From there may be many, if they are written in FormItem will be very cumbersome.
  2. Why write on FormItem prop?
    In order to determine which part of the model is carried out in the check, but also to get rules through this key prop.

Guess you like

Origin www.cnblogs.com/juyouji/p/12005509.html