element-ui表单组件

avatar
前端

写自己的表单组件

读书笔记:跑起来的车更容易转向,我们中很多人都坐在自己生活的“车库”里,坐在停着的汽车里,拼命的转动方向,若果起初方向就错啦,不启动的车是没有办法回到正确的方向上。当你发动它,你至少在某个方向上前进着,一旦车处于运动状态,你就可以轻松的掌控你手中的方向盘,即使当前方向是错的,也能很容易的调整到对的轨道上。

element-ui

element-ui强大的功能令我方程序员(vue)爱不释手,用的时候,你是否想过,别人是怎么能实现这么一个强大的ui库。接下来将展示一个手写的组件。

项目的前期工作

  • 项目初始化: vue create
  • 安装element: vue add element || npm install element
  • 启动项目:npm run serve

表单组件

mInput.vue

<!--使用-->
<m-input :value="model.username" @input="model.username = arguments[0]"></m-input>

<!--实现-->
<template>
    <div>
        <input :type="type" :value="value" @input="onInput">
    </div>
</template>

与触发父级传过来的方法,将值传出去,

<script>
export default {
    methods: {
        onInput(e) {
            let value = e.target.value
            this.$emit("input", value)
        }
    }
}
</script>

当input输入时,会触发父级传过来的input事件,改变main.vue的model数据,同时也会触发校验(mFormItem中的检验)

<!--通过触发父级emit,父级自己监听 on -->
onInput(e) {
    this.$parent.$emit("validate", value)
}

mFormItem.vue

<!--使用-->
<m-form-item label = "用户名" prop = "username">
    <m-input :value="model.username" @input="model.username = arguments[0]"></m-input>
</m-form-item>

<!--实现-->
<template>
    <div>
        <label for="">{{label}}</label>
        <div>
            <slot></slot>
            <p v-if = "errStatus">{{errMessage}}</p>
        </div>
    </div>
</template>

<script>
<!--借用element的校验器-->
import Schema from 'async-validator'
export default {
    inject: ["kForm"],
    props: ["label", "prop"],
    data() {
        return {
            errMessage: '',
            errStatus: false
        }
    },
    mounted() {
        this.$on("validate", this.validate)
    },
    methods: {
        validate() {
            const rules = this.kForm.rules[this.prop]
            const value = this.kForm.model[this.prop]
            let descripte = {[this.prop]: rules}
            let schema = new Schema(descripte)
            schema.validate({[this.prop]: value}, errors => {
                if (errors) {
                    this.errMessage = errors[0].message
                    this.errStatus = true
                }else{
                    this.errMessage = ""
                    this.errStatus = false
                }
            })
        }
    }
}
</script>

mForm.vue

<!--使用-->

<m-form :model = "model" :rules = "rules">
  <m-form-item label = "用户名" prop = "username">
    <m-input :value="model.username" @input="model.username = arguments[0]"></m-input>
  </m-form-item>
</m-form>

<!--实现-->
<template>
    <form>
        <slot></slot>
    </form>
</template>

mFrom 作为最外层的容器,其绑定了检验的规则和数据,如何传递给里面的子孙级进行相应的校验

<script>
    export defalut{
        provie(){
            return {
                mForm: this
            }
        }
    }
</script>

<!--配合inject获取-->

main.vue

<!--所需的数据-->
<script>
export default {
  data() {
    return {
      model: {
        username: "",
        password: ""
      },
      rules: {
        username: [{
          required: true,
          message: "请输入用户名"
        }],
        password: [{
          required: true,
          message: "请输入密码"
        }]
      }
    }
  }
}
</script>

整体思考几个问题

  • minput是自定义组件,如何实现对父级数据的双向数据绑定
  • mFormItem如何执行校验?如何知道input状态?怎么获取对应的数据?
  • Form是如何做全局校验,用什么方法将数据模型和校验规则传递给内部的组件?

答案

  • mInput: 里的input通过触发穿过来的input事件,以及让mFormItem 自己触发身上的事件,并将值传递出去this.$parent.$emit("validate", value)
  • mFormItem: 引用element的底层校验器async-validator,当组件挂载时监听自己在mInput上触发的方法:this.$on("validata", this.validate), 用inject获取Form传递过来的规则和数据模型。
  • Form: props接收model, rules, 利用provide将自己当参数传递给底层组件使用自己上面的数据。

以上是今日分享,希望有误的地方,欢迎大家提出来。喜欢的话可以点赞,更多的个人分享将陆续码出来。