Во фронтенд-разработке проверка формы — очень распространенная функция, некоторые библиотеки пользовательского интерфейса, такие какant.designа такжеElement uiТам достигли компонентов формы функции четности.async-validatorДанные проверки могут быть асинхронной библиотекой, ant.design с компонентами пользовательского интерфейса Form Element, используемыми async-validator. В этой статье будет кратко объяснено основное использование асинхронного валидатора и использование библиотеки, реализующей простой компонент формы с функцией проверки.
1. Базовое использование асинхронного валидатора
Функция асинхронного валидатора заключается в проверке законности данных и выдаче оперативной информации в соответствии с правилами проверки.
Ниже показано самое простое использование асинхронного валидатора.
import AsyncValidator from 'async-validator'
// 校验规则
const descriptor = {
username: [
{
required: true,
message: '请填写用户名'
},
{
min: 3,
max: 10,
message: '用户名长度为3-10'
}
]
}
// 根据校验规则构造一个 validator
const validator = new AsyncValidator(descriptor)
const data = {
username: 'username'
}
validator.validate(model, (errors, fields) => {
console.log(errors)
})
Когда данные не соответствуют правилам проверки, соответствующее сообщение об ошибке может быть получено в функции обратного вызова validator.validate.
Когда общие правила проверки в асинхронном валидаторе не могут соответствовать требованиям, мы можем написать собственные функции проверки для проверки данных. Простая функция проверки выглядит следующим образом.
function validateData (rule, value, callback) {
let err
if (value === 'xxxx') {
err = '不符合规范'
}
callback(err)
}
const descriptor = {
complex: [
{
validator: validateData
}
]
}
const validator = new AsyncValidator(descriptor)
async-validator поддерживает асинхронную проверку данных, поэтому при написании пользовательской функции проверки обратный вызов в функции проверки должен вызываться независимо от того, проходит проверка или нет.
2. Напишите компонент формы и компонент FormItem
Теперь, когда вы знаете, как использовать асинхронный валидатор, как объединить эту библиотеку с написанным компонентом формы.
Реализовать идеи
Используйте картинку, чтобы описать идею реализации.
Компонент формы
Компонент формы должен быть контейнером, содержащим переменное количество элементов формы или других элементов. Вы можете использовать встроенный в VueslotКомпоненты для представления содержимого внутри формы.
Компонент формы также должен знать, сколько компонентов FormItem необходимо проверить. В основном,Связь между родительским и дочерним компонентамиОн реализуется привязкой событий к дочерним компонентам, но здесь используется слот, и события дочерних компонентов не могут быть отслежены. Здесь вы можете передать его в компонент формы$onСлушайте событие и инициируйте пользовательское событие компонента формы до того, как FormItem будет смонтирован или уничтожен.
Согласно этой идее, сначала пишем компонент Form.
<template>
<form class="v-form">
<slot></slot>
</form>
</template>
<script>
import AsyncValidator from 'async-validator'
export default {
name: 'v-form',
componentName: 'VForm', // 通过 $options.componentName 来找 form 组件
data () {
return {
fields: [], // field: {prop, el},保存 FormItem 的信息。
formError: {}
}
},
computed: {
formRules () {
const descriptor = {}
this.fields.forEach(({prop}) => {
if (!Array.isArray(this.rules[prop])) {
console.warn(`prop 为 ${prop} 的 FormItem 校验规则不存在或者其值不是数组`)
descriptor[prop] = [{ required: true }]
return
}
descriptor[prop] = this.rules[prop]
})
return descriptor
},
formValues () {
return this.fields.reduce((data, {prop}) => {
data[prop] = this.model[prop]
return data
}, {})
}
},
methods: {
validate (callback) {
const validator = new AsyncValidator(this.formRules)
validator.validate(this.formValues, (errors) => {
let formError = {}
if (errors && errors.length) {
errors.forEach(({message, field}) => {
formError[field] = message
})
} else {
formError = {}
}
this.formError = formError
// 让错误信息的顺序与表单组件的顺序相同
const errInfo = []
this.fields.forEach(({prop, el}, index) => {
if (formError[prop]) {
errInfo.push(formError[prop])
}
})
callback(errInfo)
})
}
},
props: {
model: Object,
rules: Object
},
created () {
this.$on('form.addField', (field) => {
if (field) {
this.fields = [...this.fields, field]
}
})
this.$on('form.removeField', (field) => {
if (field) {
this.fields = this.fields.filter(({prop}) => prop !== field.prop)
}
})
}
}
</script>
Компонент FormItem
Компонент FormItem намного проще: сначала найдите компонент Form, который его содержит. Затем соответствующая информация об ошибке может быть рассчитана в соответствии с formError.
<template>
<div class="form-item">
<label :for="prop" class="form-item-label" v-if="label">
{{ label }}
</label>
<div class="form-item-content">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'form-item',
computed: {
form () {
let parent = this.$parent
while (parent.$options.componentName !== 'VForm') {
parent = parent.$parent
}
return parent
},
fieldError () {
if (!this.prop) {
return ''
}
const formError = this.form.formError
return formError[this.prop] || ''
}
},
props: {
prop: String,
label: String
}
}
</script>
FormItem также должен инициировать некоторые пользовательские события компонента Form в обработчиках mount и beforeDestroy.
<script>
export default {
// ...
methods: {
dispatchEvent (eventName, params) {
if (typeof this.form !== 'object' && !this.form.$emit) {
console.error('FormItem必须在Form组件内')
return
}
this.form.$emit(eventName, params)
}
},
mounted () {
if (this.prop) {
this.dispatchEvent('form.addField', {
prop: this.prop,
el: this.$el
})
}
},
beforeDestroy () {
if (this.prop) {
this.dispatchEvent('form.removeField', {
prop: this.prop
})
}
}
}
</script>
Наконец создайте новыйindex.js
Экспортируйте написанный компонент.
import VForm from './Form.vue'
import FormItem from './FormItem.vue'
export {
VForm,
FormItem
}
3. Как использовать
Функция проверки формы находится в компоненте Form. пройти через$refВы можете получить доступ к компоненту Form и вызвать функцию проверки, чтобы получить соответствующую информацию проверки.
Используйте следующим образом:
<template>
<v-form :model="formData" :rules="rules" ref="form">
<form-item label="手机号" prop="tel">
<input type="tel" maxlength="11" v-model.trim="formData.tel"/>
</form-item>
<button @click="handleSubmit">保存</button>
</v-form>
</template>
<script>
import { VForm, FormItem } from './common/Form'
export default {
data () {
return {
formData: {
tel: ''
},
rules: {
tel: [
{required: true, message: '您的手机号码未输入'},
{pattern: /^1[34578]\d{9}$/, message: '您的手机号码输入错误'}
]
}
}
},
methods: {
handleSubmit () {
this.$refs.form.validate(errs => {
console.log(errs)
})
}
},
components: {
VForm,
FormItem
}
}
</script>
полный код нажмитездесь.
4. Резюме
В этой статье кратко рассказывается об использовании асинхронного валидатора и реализуется компонент формы с функцией проверки. Реализованная здесь форма имеет много недостатков: (1) она проверяется только при отправке формы. (2) Компонент FormItem также должен настроить пользовательский интерфейс в соответствии с результатом проверки и выдать соответствующие подсказки. Таким образом, компоненты формы больше подходят для использования на мобильных терминалах с меньшим взаимодействием.
Вы можете написать более настраиваемые компоненты формы в соответствии с этой идеей реализации и сценариями применения.