├── App.vue
├── components
│ ├── Form.vue
│ ├── FormItem.vue
│ └── Input.vue
└── package.json
<template>
<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-item label="密码" prop="password">
<el-input v-model="form.password" ></el-input>
</el-form-item>
<el-form-item>
<el-form-item>
<button>确认提交</button>
</el-form-item>
</el-form>
</template>
<script>
import Form from './components/Form';
import FormItem from './components/FormItem';
import Input from './components/Input.vue';
export default {
components:{
'el-form':Form,
'el-form-item':FormItem,
'el-input':Input
},
data(){
return {
form:{
username:'',
password:''
},
rules:{
username:[
{required:true,message:'请输入用户名'}
],
password:[
{required:true,message:'请输入密码'}
]
}
}
}
}
</script>
<template>
<form onsubmit="return false">
<slot></slot>
</form>
</template>
<script>
export default {
props:{
model:{
type:Object
},
rules:{
type:Object
}
}
}
</script>
<template>
<div>
<label v-if="label">{{label}}</label>
<slot></slot>
<div>校验文字</div>
</div>
</template>
<script>
export default {
props:{
label:String,
prop:String
}
}
</script>
<template>
<input type="text" :value="inputValue">
</template>
<script>
export default {
props:{
value:String
},
data(){
return {inputValue:this.value}
}
}
</script>
provide(){
return {
form:this
}
},
我们在form组件中直接将当前实例暴露出去
import Vue from 'vue';
Vue.prototype.$bus = new Vue();
export default {
props:{
label:String,
prop:String
},
mounted(){
this.$bus.$on('input',(value)=>{
console.log(value)
});
}
}
我们在formItem组件中,通过eventsBus订阅input事件
<input type="text" :value="inputValue" @input="handleInput">
handleInput(e){
// 更新数据
this.inputValue = e.target.value;
this.$bus.$emit('input',{
id:this.$parent && this.$parent._uid,// 为了标识是哪个输入框
value:this.inputValue
}); // 发射输入事件
}
<template>
<div>
<label v-if="label">{{label}}</label>
<slot></slot>
<!-- 有错误 显示错误提示信息 -->
<div v-if="validateStatus === 'error'">
{{validateContent}}
</div>
</div>
</template>
<script>
import Vue from 'vue';
Vue.prototype.$bus = new Vue();
export default {
props:{
label:String,
prop:String
},
inject:['form'], // 注入父级的实例
data(){
return {
validateStatus:'', // 当前表单是否通过校验
validateContent:'' // 当前校验后的信息
}
},
methods:{
validate(value){
let rules = this.form.rules[this.prop]; // 获取当前对应的规则
rules.forEach(rule=>{
// 如果必填 并且没有值,那就出错
if(rule.required && !value){
this.validateStatus = 'error';
this.validateContent = rule.message
}else{
this.validateStatus = '';
this.validateContent = '';
}
})
}
},
mounted(){
this.$bus.$on('input',(data)=>{
if(this._uid === data.id){ // 说明更改的是当前自己的输入框
this.validate(data.value);
}
});
}
}
</script>
到目前为止基本的校验功能已经实现啦
<el-form :model="form" :rules="rules" ref="form">
<button @click="validate">确认提交</button>
validate(){ // form组件中校验是通过
this.$refs.form.validate((valid)=>{
if(valid){
alert('校验通过')
}else{
alert('校验不通过')
}
});
}
// 在form组件中检查所有的formItem是否全部通过校验
validate(cb){
cb(this.$children.every(child=>child.validateStatus!='error'))
}