最终效果:
引入表单组件,lv-form组建里边只写了一个插槽,lv-form-item组件中是验证逻辑,lv-input组件实现双向绑定和触发lv-form-item验证规则的执行。
<!--引入表单组件-->
<template>
<div>
<lv-form>
<lv-form-item label="输入框" prop="inp">
<lv-input v-model="row.inp"></lv-input>
</lv-form-item>
</lv-form>
</div>
</template>
<script>
import lvForm from './lvForm'
import lvFormItem from './lvFormItem'
import lvInput from './lvInput'
export default {
components: {lvForm,lvFormItem,lvInput},
provide(){ // 把组建实例派发出去,在lv-form-item中会用到
return {
instanceForm: this
}
},
data() {
return {
row: {
inp: '' // 双向绑定的值
},
// 验证规则
rules: {
inp: { required: true, message: '请填写账号', trigger: 'blur' }
}
}
}
}
</script>
<!--lvForm组件-->
<template>
<div>
<h1>form组件</h1>
<slot></slot>
</div>
</template>
<script>
export default {
name: "lvForm"
}
</script>
<!--lvFormItem组件-->
<template>
<div>
<label style="width:90px;">{{ label }}</label>
<slot></slot>
<span v-if="error" style="color: red; font-size: 10px;">{{ errorText }}</span><!--验证失败时要显示的数据-->
</div>
</template>
<script>
import schema from 'async-validator' // 引入验证库
export default {
name: "lvFormItem",
inject: ['instanceForm'], // 接受provide派发过来的实例,通过它可以取到实例下的任何值或方法
props:{
label: {type: String},
prop: {type: String}
},
data() {
return {
error: false,
errorText: ''
}
},
mounted() {
this.$on('validate', this.validate) // 监听组件lv-input派发的事件,从而触发validate验证方法(实际上是自己监听自己!)
},
methods: {
// 以下是async-validator的知识
validate() {
const rules = this.instanceForm.rules[this.prop] // 获取到rules prop下对应的值
const value = this.instanceForm.row[this.prop] // 获取到输入框的值,当然你也可以在lv-input组件中把输入框值传过来
const descripte = {[this.prop]: rules} // 一个描述对象key:父组件中prop传过来的属性;value:校验规则
const schema1 = new schema(descripte) // 实例化schema,把descripte传进去
// 参数一是:固定的,需要校验的key和value
schema1.validate({[this.prop]: value}, (errors, fields) => {
if(errors) { // 验证失败时,我们可以通过errors获取到验证规则中的message
this.errorText = errors[0].message
this.error = true
}else{
this.errorText = ''
this.error = false
}
})
}
}
}
</script>
<!--lvInput组件-->
<template>
<div>
<input type="text" placeholder="请输入" :value="myvalue" @input="input1">
</div>
</template>
<script>
export default {
name: "lvInput",
props: {
myvalue: {
type: String
}
},
methods: {
input1(e){
const val = e.target.value
this.$emit('input', val) // 组件双向绑定
this.$parent.$emit('validate') // 使父级触发validate事件(自己监听自己)
}
}
}
</script>