1、双向绑定原理
就是绑定value值,监听input事件
即,父组件通过props传递value值,子组件通过监听Input事件来
实时将value值通过$emit传递给父组件。
<div>
<input :type="type" :value="value" @input="onInput">
</div>
export default {
props:{
value:{
type:String,
default:''
},
type:{
type:String,
default:'text'
}
},
methods: {
onInput(e) {
let value = e.target.value;
this.$emit('input',value);
// 当值发生改变后
// 给父级组件发送一个事件
this.$parent.$emit('validate');
}
},
}
2、输入校验原理
首先确定校验组件结构,主要有三层:
- 最外层负责绑定数据模型和校验规则;
- 中间层负责校验和显示错误;
- 最底层负责改变数据同时,将数据变化实时发送给父组件;
页面布局:
<k-form :model="model" :rules="rules" >
<k-form-item label="用户名" prop="username">
<k-input v-model="model.username"></k-input>
</k-form-item>
<k-form-item label="密码" prop="password">
<k-input v-model="model.password" type="password"></k-input>
</k-form-item>
</k-form>
脚本部分:
data() {
return {
value:'',
model: { username: "tom", password: "" },
rules: {
username: [
{ required: true, message: "请输入用户名" },
{min: 6,max:10,message:'请输入6~10的用户名'}
],
password: [
{ required: true, message: "请输入密码" }
],
}
};
}
};
这里需要明确两个问题?
- FormItem是怎么知道执行校验的,它是怎么知道Input状态的?它是怎么获得对应数据模型的?
1、子组件通过this.$parent.$emit('validate');来给父组件绑定一个事件实例,
父组件通过$on来获取到这个事件,从而执行methods方法。
注意:$on必须放在mounted中执行,且只能监听自身方法,通过this.$emit的方法无法直接监听。
2、通过inject:['kForm']可以直接取用父组件的数据;
<template>
<div>
<label for="">{{label}}</label>
<div>
<slot></slot>
<p v-if="errStatus">{{errMessage}}</p>
</div>
</div>
</template>
<script>
// 引入校验类
import Schema from 'async-validator'
export default {
inject:['kForm'],
props:['label','prop'],
data() {
return {
errMessage: '',
errStatus: false
}
},
mounted(){
// 接收子组件的事件
this.$on('validate',this.validator)
},
methods: {
validator() {
// 当子组件值发生改变后,开始执行输入校验
// 有两个input! 一个用户名 一个密码
const rules = this.kForm.rules[this.prop];// 获取校验规则
const value = this.kForm.model[this.prop];// 获取要检验的参数值
// 描述对象,必须是对象,且对应规则键值。
const descriptor = {[this.prop]:rules};// 动态计算的方式设置描述对象
const schema = new Schema(descriptor);
schema.validate({[this.prop]:value},errors =>{
if(errors){
this.errMessage = errors[0].message;
this.errStatus = true;
} else {
this.errMessage = '';
this.errStatus = '';
}
})
}
},
}
</script>
- Form是怎么进行全局校验的?它用什么办法把数据模型和校验规则传递给内部组件?
1、只需要用插槽将中间校验层插入进来即可;
2、可以通过provide将当前this保存,下面任意子组件都可以通过inject取到。
这样就可以直接获取到它所绑定的数据模型和校验规则。
<template>
<form>
<slot></slot>
</form>
</template>
<script>
export default {
provide(){
return {
kForm: this
}
},
props:{
model:{
type:Object,
required:true
},
rules:{
type:Object
}
}
}
</script>
知识点:
provide and inject
只要父组件定义了provide,子组件可以直接通过inject取到值
优点:无视层级,直接取用,单向数据流中的王者!