Element Plus
的 el-form
组件是一个高度封装的表单组件,底层实现基于 Vue 3 的响应式系统和组件化设计。以下是 el-form
的核心实现思路和关键代码解析:
1. 核心功能
el-form
的主要功能包括:
- 表单数据绑定 :通过
model
属性绑定表单数据。 - 表单校验 :通过
rules
属性定义校验规则,支持内置规则和自定义规则。 - 表单方法 :提供
validate
、resetFields
、clearValidate
等方法。 - 表单布局:支持行内布局、标签对齐等功能。
2. 实现思路
(1)表单数据绑定
- 使用 Vue 3 的
provide/inject
API,将model
和rules
传递给子组件(如el-form-item
)。 el-form-item
通过inject
获取model
和rules
,并根据prop
属性绑定对应的字段。
(2)表单校验
- 使用
async-validator
库实现校验逻辑。 el-form-item
负责触发校验,并将校验结果传递给el-form
。
(3)表单方法
validate
:遍历所有el-form-item
,触发校验并汇总结果。resetFields
:重置表单数据为初始值。clearValidate
:清除校验结果。
3. 关键代码解析
以下是 el-form
的核心实现代码(简化版):
(1)el-form
组件
xml
<template>
<form @submit.prevent="onSubmit">
<slot></slot>
</form>
</template>
<script setup>
import { provide, ref } from 'vue';
const props = defineProps({
model: Object, // 表单数据
rules: Object, // 校验规则
});
const formItems = ref([]); // 存储所有 el-form-item 实例
// 提供 model 和 rules 给子组件
provide('elForm', {
model: props.model,
rules: props.rules,
addFormItem: (item) => formItems.value.push(item),
removeFormItem: (item) => {
const index = formItems.value.indexOf(item);
if (index > -1) formItems.value.splice(index, 1);
},
});
// 表单提交
const onSubmit = () => {
validate((valid) => {
if (valid) {
emit('submit');
} else {
console.log('表单校验失败');
}
});
};
// 校验整个表单
const validate = (callback) => {
let valid = true;
let count = 0;
formItems.value.forEach((item) => {
item.validate('', (error) => {
if (error) valid = false;
if (++count === formItems.value.length) {
callback(valid);
}
});
});
};
// 重置表单
const resetFields = () => {
formItems.value.forEach((item) => item.resetField());
};
// 清除校验结果
const clearValidate = (props) => {
formItems.value.forEach((item) => {
if (!props || props.includes(item.prop)) {
item.clearValidate();
}
});
};
defineExpose({
validate,
resetFields,
clearValidate,
});
</script>
(2)el-form-item
组件
ini
<template>
<div class="el-form-item">
<label class="el-form-item__label">{{ label }}</label>
<div class="el-form-item__content">
<slot></slot>
<div v-if="errorMessage" class="el-form-item__error">{{ errorMessage }}</div>
</div>
</div>
</template>
<script setup>
import { inject, ref, onMounted, onUnmounted } from 'vue';
import Schema from 'async-validator';
const props = defineProps({
label: String, // 表单项标签
prop: String, // 表单项字段名
});
const { model, rules, addFormItem, removeFormItem } = inject('elForm');
const errorMessage = ref(''); // 错误信息
// 校验表单项
const validate = (trigger, callback) => {
const rule = rules.value?.[props.prop];
if (!rule) {
callback();
return;
}
const validator = new Schema({ [props.prop]: rule });
validator.validate({ [props.prop]: model.value[props.prop] }, (errors) => {
if (errors) {
errorMessage.value = errors[0].message;
callback(errors);
} else {
errorMessage.value = '';
callback();
}
});
};
// 重置表单项
const resetField = () => {
errorMessage.value = '';
};
// 清除校验结果
const clearValidate = () => {
errorMessage.value = '';
};
// 注册到 el-form
onMounted(() => addFormItem({ validate, resetField, clearValidate, prop: props.prop }));
onUnmounted(() => removeFormItem({ validate, resetField, clearValidate, prop: props.prop }));
defineExpose({
validate,
resetField,
clearValidate,
});
</script>
4. 依赖库
async-validator
:用于实现表单校验逻辑。provide/inject
:用于在el-form
和el-form-item
之间传递数据和方法。
5. 总结
el-form
的底层实现主要包括:
- 数据绑定 :通过
provide/inject
实现父子组件通信。 - 表单校验 :使用
async-validator
库实现校验逻辑。 - 表单方法 :提供
validate
、resetFields
、clearValidate
等方法。
通过这种设计,el-form
实现了高度封装和灵活性,能够满足大多数表单场景的需求。如果你需要更深入的理解,可以查看 Element Plus 的源码:Element Plus GitHub。