1.Input组件的$emit:
🍊代码这里面就不占用太多篇幅了,手字数限制,来说下上一篇中Input组件中的this.$parent.$emit('validate',this.inputVal).,这个调用的是FormItem组件中的validate方法,这个validate方法是在FormItem组件的created生命周期中通过 this.$on("validate",this.validate)来绑定的,这里明白了,有利于理解$emit。
2.FormItem组件的逻辑实现:
下面再来明确下FormItem组件需要完成的几件事情:
- 绑定
label和prop属性 - 获取当前输入框的规则
- 如果输入框和
ruler不匹配,显示错误信息 Input组件中,用户输入内容的时候,通知FormItem的做校验(校验的方法)- 使用
async-validate做校验
//FormItem.vue
<template>
<div>
<!--如果有label显示,没有就隐藏 -->
<label v-if="label">{{label}}</label>
<!-- 插槽,用于放input组件的-->
<slot></slot>
<!-- 显示校验的错误信息-->
<p v-if="validateStatus==='error'" class="error">{{errorMessage}}</p>
</div>
</template>
<script>
//绑定label和prop属性
//获取当前输入框的规则
//如果输入框和ruler不匹配,显示错误信息
//input组件中,用户输入内容的时候,通知formItem的做校验(校验的方法)
//使用async-validate做校验
//npm i async-validator -S 安装
import Schema from 'async-validator';
export default {
data() {
return {
validateStatus:"",//校验的状态值
errorMessage:"", //显示的错误信息
}
},
inject:["form"]
,
props:{
label:{
type:String,
default:""
},
prop:{ //这个prop指的是age或者pass
type:String,
default:""
},
},
//🍊这里涉及一个生命周期的调用,子组件的内部方法先走完,走完之后再去走父组件的created方法
created() {
this.$on("validate",this.validate)
},
methods: {
validate(value){
//当前的value是输入框的值
console.log("我是输入框输入的值",value);
console.log("我是provide的form实例上的规则rules",this.form.rules);
console.log("我是prop",this.prop);
//下面开始进入校验的逻辑了
//此对象要存储校验规则这个校验规则(实际上是从Form组件中拿到的)
//让descriptor变成动态的值
// let descriptor = {};
// descriptor[this.prop] = this.form.rules[this.prop];
const descriptor ={[this.prop]:this.form.rules[this.prop]};
const validator = new Schema(descriptor);
// let obj = {};
// obj[this.prop] = value;
const obj = {[this.prop]:value }
validator.validate(obj,errors=>{
if(errors){
//显示你的错误
this.validateStatus = "error";
this.errorMessage = errors[0].message;
}else{
//错误置空
this.validateStatus = "";
this.errorMessage = "";
}
})
}
},
}
</script>
<style scoped>
.error{
color: red;
}
</style>
注意事项:
- 项目目录下需要安装
async-validator,命令行:npm i async-validator -S FormItem需要拿到外层的FormComponent组件的rules,这个需要时候可以通过provide和inject来传递一个FormComponent的实例给FormItem组件,从而拿到FormCompenent的规则rules。
3.FormComponent组件:
//FormComponent.vue
<template>
<div>
<!--插槽--用来包裹的FormItem等-->
<slot></slot>
</div>
</template>
<script>
export default {
//通过provide将自己的实例传递给内层的FormItem,这样不管中间间隔了div或者其他元素,都可以获得rules
provide(){
return{
"form":this
}
},
props:{
model:{
type:Object,
required:true
},
rules:{
type:Object
}
}
}
</script>
<style scoped>
</style>
4.三合一合成From组件:
//Form.vue
<template>
<div>
<!--这是我们自己的input组件-->
{{ruleForm}}
<m-form :model="ruleForm" :rules="rules">
<m-form-item label="用户名" prop="name">
<m-input v-model="ruleForm.name"></m-input>
</m-form-item>
<m-form-item label="年龄" prop="age">
<m-input type="age" v-model="ruleForm.age"></m-input>
</m-form-item>
<m-form-item lable="密码" prop="pass">
<m-input type="password" v-model="ruleForm.pass"></m-input>
</m-form-item>
</m-form>
</div>
</template>
<script>
import MInput from "./Input";
import MFormItem from "./FormItem";
import MForm from "./FormComponent";
export default {
components:{
MInput,
MFormItem,
MForm
},
data() {
return {
ruleForm: {
pass: '98',
age: "18",
name: "索隆",
},
rules: {
name: [
{
required: true,
message: "请输入名字"
},
{
min: 5,
max: 10,
message: "请输入5~10位用户名"
}
],
pass: [
{
require: true,
message: "请输入密码"
},
{
min: 6,
max: 10,
message: "请输入6~10密码"
}
],
age: [
{
require: true,
message: "请输入年龄",
},
],
}
};
},
methods: {
}
}
</script>
项目中通过npm run erve 运行后,可以看到相关的校验规则起作用了。