Yinput.vue 输入框
<!--
* @Author: yyg
* @Date: 2020-08-04 06:27:03
* @LastEditTime: 2020-08-04 14:25:52
* @FilePath: \新建文件夹\src\components\Yinput.vue
-->
<template>
<div>
<input :type="type" :value="value" @input="changeInput">
</div>
</template>
<script>
export default {
props: {
type: {
type: String,
default: 'text'
},
value: {
type: String,
default: ''
}
},
methods: {
changeInput (e) {
this.$emit('input', e.target.value)
this.$parent.$emit('validator')
}
}
}
</script>
<style scoped>
</style>
YformItem.vue
<!--
* @Description:
* @Date: 2020-08-04 07:07:17
-->
<template>
<div>
<slot name="info"></slot>
<label v-if="label">{{label}}</label>
<slot></slot>
<p v-if="errorMessage" class="error">{{errorMessage}}</p>
</div>
</template>
<script>
import Validator from 'async-validator'
export default {
inject: ['form'],
props: {
label: {
type: String,
default: ''
},
prop: {
type: String,
default: ''
}
},
data () {
return {
errorMessage: ''
}
},
created () {
this.$on('validator', this.validate)
},
methods: {
validate () {
return new Promise((resolve) => {
let descriptor = {[this.prop]: this.form.rules[this.prop]}
let validator = new Validator(descriptor)
validator.validate({[this.prop]: this.form.model[this.prop]}, (err) => {
if (err) {
this.errorMessage = err[0].message
resolve(false)
} else {
this.errorMessage = ''
resolve(true)
}
})
})
}
}
}
</script>
<style scoped>
.error{
color:red;
}
</style>
YForm.vue
<!--
* @Author: yang
* @Date: 2020-08-04 14:05:42
* @LastEditors: yang
* @LastEditTime: 2020-08-04 16:01:17
* @FilePath: \新建文件夹\src\components\YForm.vue
-->
<template>
<div>
<slot></slot>
</div>
</template>
<script>
export default {
provide () {
return {
form: this // 表单实例传递给子代
}
},
props: {
rules: {
type: Object
},
model: {
type: Object,
required: true
}
},
methods: {
async validate (cb) {
// map遍历执行数组的每一项,并返回一个新的数组
let arr = this.$children.filter((it) => it.prop).map(item => item.validate())
// Promise.call([promise1,promise2...])
let result = await Promise.all(arr)
// some只要数组中的其中一项满足要求 就返回true
if (result.some(valid => !valid)) {
cb(false)
} else {
cb(true)
}
}
}
}
</script>
<style scoped>
</style>
组件使用
<!--
*
*formItem显示label 执行校验 显示错误的结果
* input 绑定数据模型 通知formItem 执行校验
* form 提供数据模型 校验规则
-->
<template>
<div class="hello">
<y-form ref="kForm" :model="model" :rules="rules">
<YformItem label="姓名" prop="name">
<Yinput :value="model.name" @input="model.name=$event"></Yinput>
</YformItem>
<YformItem label="密码" prop="password">
<Yinput type="password" :value="model.password" @input="model.password=$event"></Yinput>
</YformItem>
<YformItem>
<button @click="submit('kForm')">提交</button>
</YformItem>
</y-form>
</div>
</template>
<script>
import Yinput from './Yinput.vue'
import YformItem from './YformItem.vue'
import YForm from './YForm.vue'
export default {
name: 'HelloWorld',
data () {
return {
model: {
name: 'sss',
password: ''
},
rules: {
name: [
{ required: true, message: '请输入姓名', trigger: 'change' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'change' }
]
}
}
},
components: {
Yinput,
YformItem,
YForm
},
methods: {
submit (formName) {
this.$refs[formName].validate((validate) => {
if (validate) {
console.log(validate)
console.log('成功了')
} else {
console.log(validate)
console.log('失败了')
}
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>