Form表单的实现原理
原理非常简单:基于vue中的v-model,通过传入的值和规则进行匹配和处理
先看想要实现的功能
这边只谈最常用的提交,重置,校验
<script setup>
import Form from '@/components/Form/index.vue'
import FormItem from '@/components/FormItem/index.vue'
import ComInput from '@/components/ComInput/index.vue'
import { ref } from 'vue';
const formRef = ref(null)
const formData = ref({
text: '',
})
// 规则
const rules = {
text: {
required: true,
message: '请输入申请原因',
validateField: (value) => {
if (value.length < 10) {
return '申请原因不能少于10个字'
} else {
return false
}
}
},
}
// 提交
const submit = () => {
const res = formRef.value.validateForm()
}
// 重置
const reset = () => {
formRef.value.resetForm()
}
</script>
<template>
<Form ref="formRef" v-model="formData" :rules="rules">
<FormItem label="文本" name="text" required>
<ComInput placeholder="请输入文本" v-model="formData.text" />
</FormItem>
</Form>
<button @click="submit">提交</button>
<button @click="reset">重置</button>
</template>
Form组件的实现
<script lang="ts" setup>
import { ref, provide, PropType, onMounted } from 'vue'
const props = defineProps({
modelValue: {
type: Object,
default: () => ({})
},
rules: {
type: Object as PropType<{
[key: string]: {
required?: boolean;
message?: string;
validateField?: any;
}
}>,
default: () => ({})
}
})
// 用于存储formitem的一系列方法
const formItems = ref<any>({});
// 用于存放初始化的值
const initForm = ref<any>({});
const emit = defineEmits(['update:modelValue'])
// 要将这个函数通过provide传递给FormItem组件
const setFormItemList = (name: string, options: any) => {
formItems.value[name] = options
};
// 实现校验功能
const validateForm = () => {
// 这边用来判断FormItem上的required标志
Object.values(formItems.value).forEach((item: any) => {
if (item.required && !props.modelValue[item.name]) {
alert('不能为空')
return false
}
})
// 这边用来判断rules
for(let key in props.modelValue){
if (props.rules[key]) {
if (props.rules[key].required && !props.modelValue[key]) {
uni.showToast({
title: props.rules[key].message,
icon: 'none'
})
return false
}
if (props.rules[key].validateField) {
const res = props.rules[key].validateField(props.modelValue[key])
if (res) {
uni.showToast({
title: res,
icon: 'none'
})
return false
}
}
}
}
};
// 重置为初始化
const resetForm = () => {
emit('update:modelValue', initForm.value)
}
// 传递给FormItem
provide('setFormItemList', setFormItemList)
// 抛出方法
defineExpose({
validateForm,
resetForm
})
// 将初始化的值设置进去
onMounted(() => {
initForm.value = JSON.parse(JSON.stringify(props.modelValue))
})
</script>
<template>
<slot></slot>
</template>
FormItem的设置
<script lang='ts' setup>
import { inject, ref, onMounted } from 'vue';
const props = defineProps({
name: {
type: String,
required: true
},
label: {
type: String,
required: true
},
required: {
type: Boolean,
default: false
},
})
const setFormItemList:any = inject('setFormItemList')
onMounted(() => {
setFormItemList(props.name, {
name: props.name,
label: props.label,
required: props.required
})
})
</script>
以上就是基本设置,还有一些清理校验,或将校验字段设置在输入框底下之类的,都可以基于这个模板继续改造