高仿一个element的form组件

实现elementui的form组件

目标实现
  • 实现element的表单绑定和校验
  • 回顾vue组件传值的方式
  • 学习promise的源码实现
  1. EInput组件
<template>
  <div>
      // 使用v-bind="$attrs" 让子组件继承父组件全部的属性,这样子组件就不用接受父组件传入的值
      // 如type,pleaseholder等属性
    <input :value="valueInInput" @input="handleInput" v-bind="$attrs" />
  </div>
</template>

<script>
export default {
  name: 'EInput',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      // 保证单项数据流
      valueInInput: this.value
    }
  },
  methods: {
    handleInput (e) {
      this.valueInInput = e.target.value;
      this.$emit('input', this.valueInInput)
    }
  }

}
</script>

<style>
</style>
  1. EFromItem组件
  • 安装async-validator,用于表单的验证
<template>
  <div>
    <label v-if="label">{{label}}</label>
    <slot></slot>
    <p v-if="errorMessage" class="error">{{ errorMessage }}</p>
    <!-- {{form.rules}} -->
  </div>
  
</template>

<script>
import Schema from 'async-validator'
// import { error } from 'shelljs/src/common';
export default {
   // 接受父组件的传入
  inject: ['form'],
  name: 'EFormItem',
  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]
      const desc = { [this.prop]: rules }
      const schema = new Schema(desc)
      return schema.validate({ [this.prop]: value }, errors => {
        if (errors) {
          this.errorMessage = errors[0].message
        } else {
          this.errorMessage = ''
        }
      })
    }
  }

}
</script>

<style scoped>
.error {
  color: red;
}
</style>
  1. EFrom组件
  • 使用provide传入一个form的值,这个值会把form全部的属性所有存入
  • validate 提供一个返回的promise的集合
<template>
  <div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'EForm',
  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(() => {
        return cb(true)
      }).catch(() => {
        return cb(false)
      })
    }
  }
}
</script>

<style>
</style>
相关文章
相关标签/搜索