高仿一個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>
相關文章
相關標籤/搜索