写入Input.vue组件,即实现v-model语法糖和传入type类型可改变input类型
<template>
<input :type="type" :value="inputValue" @input="inputHandle" />
</template>
<script>
export default {
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
default: 'text'
}
},
data () {
return {
inputValue: this.value
}
},
methods: {
inputHandle (e) {
this.inputValue = e.target.value
this.$emit('input', this.inputValue)
}
}
}
</script>
先理解插槽,即一个组件中加入slot后,可以在使用这个组件时加入自定义内容
定义一个插槽
<template>
<div>
<div class="header">
header:
<slot name="header"></slot>
</div>
<slot></slot>
<div class="footer">
footer:
<slot name="footer"></slot>
</div>
</div>
</template>
使用这个插槽组件,具名的插槽所占的位置会被同名template模板中的内容替换
<template>
<div id="app">
<form-test></form-test>
<win>
<template slot="header">头部</template>
content
<template slot="footer">尾部</template>
</win>
</div>
</template>
FormItem组件中写入内容,插槽处可以插入input标签
<template>
<div>
<label v-if="label">{{label}}</label>
<div>
<slot></slot>
<p v-if="validataStatus ==='error'">{{errorMessage}}</p>
</div>
</div>
</template>
<script>
export default {
props: ['label', 'prop'],
data () {
return {
validataStatus: '',
errorMessage: ''
}
}
}
</script>
Form组件中写入
<template>
<form>
<slot></slot>
</form>
</template>
<script>
export default {
provide () {
return {
form: this
}
},
props: {
model: {
type: Object,
required: true
},
rules: {
type: Object
}
}
}
</script>
这样我们就可以使用了
<k-form :model="ruleForm" :rules="rules">
<form-item label="用户名" prop="name">
<k-input v-model="ruleForm.name"></k-input>
</form-item>
<form-item label="密码" prop="pwd">
<k-input v-model="ruleForm.pwd" type="password"></k-input>
</form-item>
{{ruleForm}}
</k-form>
Form组件需要传入模型数据和校验规则
FormItem组件需要传入标签名和单个校验规则
Input组件需要传入显示的value值和input类型
组件设计中常用到的provide和inject
祖先组件往下传值
provide () {
return {
name: '这是祖先组件的名字'
}
}
后代组件接值,类似于props
inject: ['name']
也可以传整个组件实例
provide () {
return {
form: this
}
}
this表示整个form组件实例
后代组件可以通过form.数据获取到所有数据
需要校验input中的value是否符合校验项,使用在子组件中使用父组件派发事件,在父组件中监听自己派发的事件
this.$parent.$emit()方法
input组件
<template>
<input :type="type" :value="inputValue" @input="inputHandle" />
</template>
<script>
export default {
inject: ['name'],
props: {
value: {
type: String,
default: ''
},
type: {
type: String,
default: 'text'
}
},
data () {
return {
inputValue: this.value
}
},
methods: {
inputHandle (e) {
this.inputValue = e.target.value
this.$emit('input', this.inputValue)
this.$parent.$emit('validate', this.inputValue)
}
}
}
</script
FormItem组件
<template>
<div>
<label v-if="label">{{label}}</label>
<div>
<slot></slot>
<p v-if="validateStatus ==='error'">{{errorMessage}}</p>
</div>
</div>
</template>
<script>
import Schema from 'async-validator'
export default {
props: ['label', 'prop'],
inject: ['form'], // 注入form实例,获取model和校验规则
data () {
return {
validateStatus: '',
errorMessage: ''
}
},
created () {
// 监听input中value变化
this.$on('validate', this.validate)
},
methods: {
validate (value) {
// 校验当前项
const descriptor = { [this.prop]: this.form.rules[this.prop] } // 校验规则
// 校验器
const validator = new Schema(descriptor)
validator.validate({ [this.prop]: value }, errors => {
if (errors) {
this.validateStatus = 'error'
this.errorMessage = errors[0].message
} else {
this.validateStatus = this.errorMessage = ''
}
})
}
}
}
</script>