useSchema 表单架构钩子函数文档
一、功能概述
useSchema 是基于 Formily 和 Vue 3 的表单架构管理钩子,用于实现表单组件的注册、绑定与动态管理。它通过桥接 Formily 的 Schema 系统与 UI 组件库(如 Element Plus),提供了灵活的组件注册机制,支持公共组件与自定义组件的分层管理,适用于复杂表单场景的组件扩展与定制。
二、核心特性
组件分层管理
- 公共组件库(
publicComponentStore):内置 Element Plus 常用表单组件(如Input、Radio、Checkbox等),支持全局覆盖。 - 自定义组件库(
customComponentStore):用于注册应用内自定义组件,优先级高于公共组件。
- 公共组件库(
动态组件注册
通过setFormilyComponent方法动态注册组件,支持指定组件类型(公共/自定义),实现组件的按需加载与替换。响应式 Schema 生成
使用computed生成响应式的FormilySchema,确保组件变更时自动更新表单架构。
三、核心概念与接口
1. 组件类型枚举(FormilyComponentType)
typescript
export enum FormilyComponentType {
PUBLIC, // 公共组件(全局作用域,可被自定义组件覆盖)
CUSTOM // 自定义组件(应用作用域,优先级高于公共组件)
}2. 组件存储接口(SchemaVueComponents)
typescript
interface SchemaVueComponents {
[key: string]: VueComponent // 组件名到 Vue 组件的映射
}3. 返回值说明
| 名称 | 类型 | 说明 |
|---|---|---|
FormilySchema | ComputedRef<SchemaField> | 响应式 Formily Schema 实例,用于在模板中渲染表单组件 |
setFormilyComponent | (name: string, component: VueComponent, type?: FormilyComponentType) => void | 注册组件的方法 |
四、使用流程
1. 基础使用:渲染内置组件
vue
<template>
<FormilySchema
:schema="{
type: 'object',
properties: {
username: {
type: 'string',
title: '用户名',
'x-component': 'Input' // 使用内置 Input 组件
}
}
}"
/>
</template>
<script setup>
import { useSchema } from './useSchema'
const { FormilySchema } = useSchema()
</script>2. 注册自定义组件(覆盖内置组件)
vue
<template>
<FormilySchema
:schema="{
type: 'object',
properties: {
password: {
type: 'string',
title: '密码',
'x-component': 'CustomPasswordInput' // 使用自定义组件
}
}
}"
/>
</template>
<script setup>
import { useSchema } from './useSchema'
import CustomPasswordInput from './CustomPasswordInput.vue' // 自定义密码输入组件
const { setFormilyComponent } = useSchema()
// 注册自定义组件到自定义作用域(CUSTOM 类型可省略)
setFormilyComponent('CustomPasswordInput', CustomPasswordInput)
</script>3. 全局覆盖公共组件(如修改 Input 样式)
typescript
// 在全局初始化文件中
import { useSchema } from './useSchema'
import { Input } from '@formily/element-plus'
import CustomInput from './CustomInput.vue'
const { setFormilyComponent } = useSchema()
// 覆盖公共组件库中的 Input 组件
setFormilyComponent('Input', CustomInput, FormilyComponentType.PUBLIC)五、API 详解
setFormilyComponent 方法
参数说明
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | 是 | - | 组件名称(需与 Schema 中 x-component 一致) |
component | VueComponent | 是 | - | Vue 组件(可以是 defineComponent 或组件引用) |
type | FormilyComponentType | 否 | FormilyComponentType.CUSTOM | 组件类型(公共/自定义) |
示例:注册公共组件
typescript
// 注册一个公共组件(所有表单实例均可访问)
setFormilyComponent('MyButton', MyButtonComponent, FormilyComponentType.PUBLIC)六、注意事项
组件命名冲突
- 自定义组件(
CUSTOM)会覆盖同名的公共组件(PUBLIC)。 - 公共组件会覆盖 Formily 内置的默认组件(如
Input)。
- 自定义组件(
组件通信要求
自定义组件需遵循 Formily 的 组件协议,至少包含value、onChange等属性。性能优化
- 避免在高频更新场景中动态注册组件,建议在组件初始化阶段完成注册。
- 大型项目可通过
defineAsyncComponent实现组件的异步加载。
七、扩展场景
场景 1:动态切换组件库(Element Plus ↔ Ant Design)
typescript
// 定义组件库映射
const componentLibs = {
element: {
Input: () => import('@formily/element-plus').Input,
Button: () => import('@formily/element-plus').Button
},
antd: {
Input: () => import('@formily/antd').Input,
Button: () => import('@formily/antd').Button
}
}
// 动态切换组件库
function switchComponentLib(libName: 'element' | 'antd') {
const lib = componentLibs[libName]
Object.keys(lib).forEach(name => {
setFormilyComponent(name, lib[name], FormilyComponentType.PUBLIC)
})
}场景 2:基于 Props 动态渲染组件
vue
<template>
<FormilySchema
:schema="{
type: 'object',
properties: {
field: {
type: 'string',
title: '动态组件',
'x-component': dynamicComponentName, // 动态组件名
'x-component-props': { size: 'large' } // 组件 Props
}
}
}"
/>
</template>
<script setup>
import { ref } from 'vue'
import { useSchema } from './useSchema'
const dynamicComponentName = ref('Input') // 可通过逻辑动态修改为 'Select'、'Textarea' 等
const { FormilySchema } = useSchema()
</script>八、依赖说明
- 核心依赖:
@formily/vue:Formily 的 Vue 适配层@formily/element-plus:Element Plus 组件库适配(示例中使用,可替换为其他库)
- Vue 版本:需使用 Vue 3.x(Composition API 支持)
- 类型声明:依赖
@formily/vue/type-artefacts提供的类型定义
