1、正常使用el-form的情况如下:
<el-form :model="form" :rules="rules">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username"></el-input>
<el-form-item>
</el-form>
由基本的使用方法可以知道,form表单实现了三个组件,分别是form,form-item,以及input,将form表单的数据放在form中,提供给后代组件。而form-item主要进行组件的校验。el-input则实现输入事件。
2、form的实现
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
provide() {
return {
form: this
}
},
props: {
model: {
type: Object,
default: () => {},
required: true,
},
rules: {
type: Object,
default: () => {}
}
},
data() {
return {
validate(cb) {
const results = this.$children.filter(item => item.prop).map(item => item.validate())
Promise.all(results).then(() => cb(true)).catch(() => cb(false))
}
}
},
}
</script>
<style lang="less">
</style>
form表单主功能是通能过插槽展示子组件,通过provide/inject将form传递给子组件。
3、form-item的实现
<template>
<div>
<!-- 1.label -->
<label v-if="label">{{label}}</label>
<!-- 2.内部内容 -->
<slot></slot>
<!-- 3.校验结果 -->
<p v-if="error">{{error}}</p>
<p>{{form.rules[this.prop]}}</p>
</div>
</template>
<script>
import Validator from 'async-validator'
export default {
inject: ['form'],
props: {
label: {
type: String,
default: ''
},
prop: {
type: String,
default: ''
}
},
data() {
return {
error: ''
}
},
mounted() {
this.$on('validate', () => {
this.validate()
})
},
methods: {
validate() {
const rules = this.form.rules[this.prop]
const value = this.form.model[this.prop]
const validator = new Validator({[this.prop]: rules})
return validator.validate({[this.prop]: value}, errors => {
if(errors) {
this.error = errors[0].message
} else {
this.error = ''
}
})
}
},
}
</script>
<style lang="less">
</style>
form-item主要功能是接受父组件传递form中所拥有的form的值和校验规则,同时通过async-validator进行规则校验,同时将校验结果显示。
4、input的实现
<template>
<div>
<input :type="type" :value="value" @input="onInput" v-bind="$attrs">
</div>
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
default: 'text'
}
},
data() {
return {
}
},
methods: {
onInput(e) {
this.$emit('input', e.target.value);
this.$parent.$emit('validate');
}
},
}
</script>
<style lang="less" scoped>
</style>
input主要进行dom层的实现,同时通过input输入事件,输入框的双向绑定。通过$attrs将父组件中没有通过props传递下来的值进行接收,例如:placeholder
5、新建一个index.vue,将各个组件引入并使用。
<template>
<div>
<cform :model="form" :rules="rules" ref="form">
<citem label="用户名'" prop="username">
<cinput v-model="form.username" placeholder="用户名"></cinput>
</citem>
<citem><button @click="onLogin">登录</button></citem>
</cform>
</div>
</template>
<script>
import cform from './cform'
import citem from './citem'
import cinput from './cinput'
export default {
components: {
cform,
citem,
cinput
},
data() {
return {
form: {
username: ''
},
rules: {
username: [{ required: true, message: "用户名为必填项" }],
}
}
},
methods: {
onLogin() {
this.$refs.form.validate((isValide) => {
console.log(isValide);
})
}
},
}
</script>
<style lang="less" scope>
</style>
一个简单的form表单实现了,这里只是实现了基本的input的表单校验功能。想了解的小伙伴可以自己添加功能。