@leiyin/v-form-renderer 0.1.3-alpha.4 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +216 -0
- package/package.json +5 -2
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# @leiyin/v-form-renderer
|
|
2
|
+
|
|
3
|
+
一个基于 Vue 3 + Element Plus 的配置化表单渲染组件,用 JSON/Schema 快速生成复杂表单。
|
|
4
|
+
|
|
5
|
+
## ✨ 特性
|
|
6
|
+
- 配置驱动(Content Schema)
|
|
7
|
+
- 支持 group 嵌套、动态显隐与禁用
|
|
8
|
+
- v-model 双向绑定与方法暴露
|
|
9
|
+
- 远程选项加载与自定义组件
|
|
10
|
+
- 完整 TypeScript 类型与 ESM/CJS 构建
|
|
11
|
+
|
|
12
|
+
## 📦 安装
|
|
13
|
+
- peerDependencies:vue ^3.2.0、element-plus 2.11.7
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @leiyin/v-form-renderer
|
|
17
|
+
# 或
|
|
18
|
+
npm install @leiyin/v-form-renderer
|
|
19
|
+
# 或
|
|
20
|
+
yarn add @leiyin/v-form-renderer
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 🚀 基础用法
|
|
24
|
+
```vue
|
|
25
|
+
<template>
|
|
26
|
+
<VFormRenderer :content="schema" />
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
import { ref } from 'vue'
|
|
31
|
+
import VFormRenderer from '@leiyin/v-form-renderer'
|
|
32
|
+
|
|
33
|
+
const schema = ref([
|
|
34
|
+
{ id: 'username', type: 'input', label: '用户名', el: { placeholder: '请输入' }, default: '' },
|
|
35
|
+
{ id: 'role', type: 'select', label: '角色', options: [
|
|
36
|
+
{ label: '管理员', value: 'admin' },
|
|
37
|
+
{ label: '普通用户', value: 'user' }
|
|
38
|
+
] }
|
|
39
|
+
])
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 🔗 v-model 与方法
|
|
44
|
+
- v-model:使用 v-model:model 绑定整个表单对象
|
|
45
|
+
- 方法暴露:通过 ref 获取实例并调用内置方法
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<template>
|
|
49
|
+
<VFormRenderer
|
|
50
|
+
v-model:model="form"
|
|
51
|
+
:content="schema"
|
|
52
|
+
ref="formRef"
|
|
53
|
+
@enter="onEnter"
|
|
54
|
+
/>
|
|
55
|
+
</template>
|
|
56
|
+
|
|
57
|
+
<script setup lang="ts">
|
|
58
|
+
import { ref } from 'vue'
|
|
59
|
+
import VFormRenderer, { type VFormRendererInstance } from '@leiyin/v-form-renderer'
|
|
60
|
+
|
|
61
|
+
const form = ref<Record<string, any>>({})
|
|
62
|
+
const formRef = ref<VFormRendererInstance>()
|
|
63
|
+
|
|
64
|
+
const onEnter = () => {
|
|
65
|
+
// 回车事件
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const getValue = () => {
|
|
69
|
+
const result = formRef.value?.getFormValue() // outputFormat 后的值
|
|
70
|
+
console.log(result)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const validate = async () => {
|
|
74
|
+
const ok = await formRef.value?.validate()
|
|
75
|
+
console.log('valid:', ok)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const reset = () => {
|
|
79
|
+
formRef.value?.resetFields()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const patch = () => {
|
|
83
|
+
formRef.value?.updateForm({ username: '张三' })
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
方法来源与实现参考:
|
|
89
|
+
- 组件实现 [v-form-renderer.vue](file:///v-form-renderer/src/v-form-renderer.vue)
|
|
90
|
+
- 方法定义 [useFormEvents.ts](file:///v-form-renderer/src/hooks/useFormEvents.ts#L1-L75)
|
|
91
|
+
- Props 定义 [v-form-renderer.ts](file:///v-form-renderer/src/v-form-renderer.ts#L1-L31)
|
|
92
|
+
|
|
93
|
+
## ⚙️ Props
|
|
94
|
+
- content: Content[] 必填,表单 Schema
|
|
95
|
+
- labelWidth: string,统一 label 宽度,默认 98px
|
|
96
|
+
- disabled: boolean,禁用整个表单
|
|
97
|
+
- inline: boolean,行内表单,默认 true
|
|
98
|
+
- readonly: boolean,只读模式(input 显示文本,select 显示 label)
|
|
99
|
+
- 透传:支持 Element Plus el-form 的其余属性与事件(使用 v-bind="$attrs")
|
|
100
|
+
|
|
101
|
+
## 🧩 Content Schema
|
|
102
|
+
类型定义参考 [form.ts](file:///v-form-renderer/src/types/form.ts#L1-L109)
|
|
103
|
+
|
|
104
|
+
常用字段:
|
|
105
|
+
- id: string,唯一键,作为数据 key
|
|
106
|
+
- label: string | Function,表单项标题;支持组件函数
|
|
107
|
+
- type: string,例如 'input' | 'select' | 'radio-group' | 'checkbox-group' | 'cascader' | 'group'
|
|
108
|
+
- el: Record<string, any>,对应组件的属性,如 placeholder、multiple 等
|
|
109
|
+
- default: any,初始默认值
|
|
110
|
+
- items: Content[],当 type='group' 时的子项
|
|
111
|
+
- hidden(formValue, item): boolean,返回 true 隐藏
|
|
112
|
+
- disabled(formValue, item): boolean,返回 true 禁用
|
|
113
|
+
- options: { label: string; value?: any }[],选择类组件选项
|
|
114
|
+
- component: 自定义组件,优先于 type 的内置组件
|
|
115
|
+
- inputFormat(obj): any,处理输入值(default/v-model/updateForm)
|
|
116
|
+
- outputFormat(val, obj): any,处理输出值(getFormValue 时应用)
|
|
117
|
+
- rules: FormItemRule[],Element Plus 校验规则
|
|
118
|
+
- remote: 远程 prop/选项加载(select/radio/checkbox 支持自动映射)
|
|
119
|
+
- on: 事件监听回调,签名为 (args, updateForm, setOptions) => void
|
|
120
|
+
|
|
121
|
+
示例:group 嵌套
|
|
122
|
+
```ts
|
|
123
|
+
const schema = [
|
|
124
|
+
{
|
|
125
|
+
id: 'user',
|
|
126
|
+
type: 'group',
|
|
127
|
+
label: '用户信息',
|
|
128
|
+
items: [
|
|
129
|
+
{ id: 'name', type: 'input', label: '姓名', default: '' },
|
|
130
|
+
{ id: 'age', type: 'input', label: '年龄', el: { type: 'number' } }
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 🌐 远程选项加载
|
|
137
|
+
```ts
|
|
138
|
+
const schema = [
|
|
139
|
+
{
|
|
140
|
+
id: 'city',
|
|
141
|
+
type: 'select',
|
|
142
|
+
label: '城市',
|
|
143
|
+
remote: {
|
|
144
|
+
// 返回 Promise 的方法(可传入 params)
|
|
145
|
+
url: (params) => fetch(`/api/cities?kw=${params.kw}`).then(r => r.json()),
|
|
146
|
+
dataPath: 'data.list', // 响应体中数据路径
|
|
147
|
+
label: 'name', // 用作 label 的字段
|
|
148
|
+
value: 'code' // 用作 value 的字段
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
```
|
|
153
|
+
当为 select/radio-group/checkbox-group 时,远程数据会自动映射为 Element Plus 的选项。
|
|
154
|
+
实现参考 [RenderFormItem.vue](file:///v-form-renderer/src/components/RenderFormItem.vue#L194-L247)。
|
|
155
|
+
|
|
156
|
+
## 👁️ 只读与显隐
|
|
157
|
+
- readonly: true 时,input 显示文本、select 显示选中项 label
|
|
158
|
+
- hidden/disabled:传入函数,依据当前 formModel 动态控制
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
const schema = [
|
|
162
|
+
{
|
|
163
|
+
id: 'level',
|
|
164
|
+
type: 'select',
|
|
165
|
+
label: '级别',
|
|
166
|
+
options: [{ label: 'A', value: 'A' }, { label: 'B', value: 'B' }]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: 'extra',
|
|
170
|
+
type: 'input',
|
|
171
|
+
label: '额外信息',
|
|
172
|
+
hidden: (form) => form.level !== 'A'
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## 🎯 校验与重置
|
|
178
|
+
- 使用 Element Plus 的规则校验(rules)
|
|
179
|
+
- validate(): Promise<boolean | void>
|
|
180
|
+
- resetFields(): 重置为 default 值并清除校验
|
|
181
|
+
|
|
182
|
+
参考 [useFormEvents.ts](file:///v-form-renderer/src/hooks/useFormEvents.ts#L20-L44)。
|
|
183
|
+
|
|
184
|
+
## 🧱 插槽与自定义
|
|
185
|
+
- 命名插槽:以 id 为名注入内容,例如 #id:username
|
|
186
|
+
- label 组件:将 label 设置为组件/函数,渲染自定义标题
|
|
187
|
+
- 自定义组件:传入 component 替代内置 Element Plus 组件
|
|
188
|
+
|
|
189
|
+
```vue
|
|
190
|
+
<template>
|
|
191
|
+
<VFormRenderer :content="schema">
|
|
192
|
+
<template #id:username>
|
|
193
|
+
<span style="margin-right: 8px">用户名扩展内容</span>
|
|
194
|
+
</template>
|
|
195
|
+
</VFormRenderer>
|
|
196
|
+
</template>
|
|
197
|
+
|
|
198
|
+
<script setup lang="ts">
|
|
199
|
+
const schema = [
|
|
200
|
+
{
|
|
201
|
+
id: 'username',
|
|
202
|
+
type: 'input',
|
|
203
|
+
label: '用户名',
|
|
204
|
+
el: { placeholder: '请输入' }
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
</script>
|
|
208
|
+
```
|
|
209
|
+
插槽实现参考 [v-form-renderer.vue](file:///v-form-renderer/src/v-form-renderer.vue#L60-L83) 与渲染器 [render-component.ts](file:///v-form-renderer/src/components/render-component.ts#L1-L33)。
|
|
210
|
+
|
|
211
|
+
## 📚 导入与类型
|
|
212
|
+
- 默认导出:VFormRenderer
|
|
213
|
+
- 类型导出:Content、VFormProps、VFormRendererInstance 等
|
|
214
|
+
|
|
215
|
+
入口参考 [index.ts](file:///v-form-renderer/src/index.ts)。
|
|
216
|
+
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leiyin/v-form-renderer",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Base on element-ui, Render form-item easily",
|
|
5
|
+
"author": "leiyin <lyyray18@163.com>",
|
|
4
6
|
"main": "dist/index.cjs.js",
|
|
5
7
|
"module": "dist/index.esm.js",
|
|
8
|
+
"sideEffects": false,
|
|
6
9
|
"types": "dist/index.d.ts",
|
|
7
10
|
"files": [
|
|
8
11
|
"dist"
|
|
@@ -40,5 +43,5 @@
|
|
|
40
43
|
"vue": "^3.2.0",
|
|
41
44
|
"vue-tsc": "^3.2.1"
|
|
42
45
|
},
|
|
43
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "30f5c983279a5ba30464eac365dfab873eb88d8a"
|
|
44
47
|
}
|