仿照elementUI编写自己的表单组件

Yinput.vue 输入框

<!--
 * @Author: yyg
 * @Date: 2020-08-04 06:27:03
 * @LastEditTime: 2020-08-04 14:25:52
 * @FilePath: \新建文件夹\src\components\Yinput.vue
-->
<template>
    <div>
        <input :type="type" :value="value" @input="changeInput">
    </div>
</template>

<script>
export default {
  props: {
    type: {
      type: String,
      default: 'text'
    },
    value: {
      type: String,
      default: ''
    }
  },
  methods: {
    changeInput (e) {
      this.$emit('input', e.target.value)
      this.$parent.$emit('validator')
    }
  }
}
</script>

<style scoped>

</style>

YformItem.vue

<!--
 * @Description:
 * @Date: 2020-08-04 07:07:17
-->
<template>
    <div>
      <slot name="info"></slot>
       <label v-if="label">{{label}}</label>
       <slot></slot>
       <p v-if="errorMessage" class="error">{{errorMessage}}</p>
    </div>
</template>

<script>
import Validator from 'async-validator'
export default {
  inject: ['form'],
  props: {
    label: {
      type: String,
      default: ''
    },
    prop: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      errorMessage: ''
    }
  },
  created () {
    this.$on('validator', this.validate)
  },
  methods: {
    validate () {
      return new Promise((resolve) => {
        let descriptor = {[this.prop]: this.form.rules[this.prop]}
        let validator = new Validator(descriptor)
        validator.validate({[this.prop]: this.form.model[this.prop]}, (err) => {
          if (err) {
            this.errorMessage = err[0].message
            resolve(false)
          } else {
            this.errorMessage = ''
            resolve(true)
          }
        })
      })
    }
  }
}
</script>

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

YForm.vue

<!--
 * @Author: yang
 * @Date: 2020-08-04 14:05:42
 * @LastEditors: yang
 * @LastEditTime: 2020-08-04 16:01:17
 * @FilePath: \新建文件夹\src\components\YForm.vue
-->
<template>
    <div>
        <slot></slot>
    </div>
</template>

<script>
export default {
  provide () {
    return {
      form: this // 表单实例传递给子代
    }
  },
  props: {
    rules: {
      type: Object
    },
    model: {
      type: Object,
      required: true
    }
  },
  methods: {
    async validate (cb) {
      // map遍历执行数组的每一项,并返回一个新的数组
      let arr = this.$children.filter((it) => it.prop).map(item => item.validate())
      //   Promise.call([promise1,promise2...])
      let result = await Promise.all(arr)
      // some只要数组中的其中一项满足要求 就返回true
      if (result.some(valid => !valid)) {
        cb(false)
      } else {
        cb(true)
      }
    }
  }

}
</script>

<style  scoped>

</style>

组件使用

<!--
 *
 *formItem显示label  执行校验  显示错误的结果
 * input  绑定数据模型   通知formItem 执行校验
 * form  提供数据模型  校验规则
-->
<template>
  <div class="hello">
    <y-form ref="kForm" :model="model" :rules="rules">
    <YformItem label="姓名" prop="name">
        <Yinput :value="model.name"  @input="model.name=$event"></Yinput>
    </YformItem>
    <YformItem label="密码" prop="password">
          <Yinput type="password" :value="model.password" @input="model.password=$event"></Yinput>
    </YformItem>
    <YformItem>
        <button @click="submit('kForm')">提交</button>
    </YformItem>
    </y-form>
  </div>
</template>

<script>
import Yinput from './Yinput.vue'
import YformItem from './YformItem.vue'
import YForm from './YForm.vue'
export default {
  name: 'HelloWorld',
  data () {
    return {
      model: {
        name: 'sss',
        password: ''
      },
      rules: {
        name: [
          { required: true, message: '请输入姓名', trigger: 'change' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'change' }
        ]
      }
    }
  },
  components: {
    Yinput,
    YformItem,
    YForm
  },
  methods: {
    submit (formName) {
      this.$refs[formName].validate((validate) => {
        if (validate) {
          console.log(validate)
          console.log('成功了')
        } else {
          console.log(validate)
          console.log('失败了')
        }
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值