fy-dynamic-form
v0.2.2
Published
Vue 3 drag-and-drop form builder with standalone renderer. Design forms visually and export as JSON.
Maintainers
Readme
dynamic-form-builder
基于 Vue 3 + TypeScript + Element Plus 的表单构建器 npm 包。导出两个组件:
FormBuilder— 拖拽式表单设计器(三栏布局:组件面板 + 画布 + 属性面板)FormRender— 根据 JSON 配置渲染可交互表单
安装
npm install fy-dynamic-form使用者项目只需额外安装以下两个依赖(其余依赖由 npm 自动安装):
npm install vue@^3.5 element-plus@^2.9
pinia也是必需的 peer dependency,安装 Element Plus 时通常已间接依赖它。如果项目中没有,手动npm install pinia即可。
必需的项目初始化
// main.ts — 只需导入 Vue、Element Plus、Pinia,以及我们的 CSS
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createPinia } from 'pinia'
import 'fynix-dynamic-form-builder/dist/style.css'
const app = createApp(App)
app.use(createPinia())
app.use(ElementPlus)
app.mount('#app')使用方法
FormBuilder — 表单设计器
<script setup lang="ts">
import { FormBuilder } from 'dynamic-form-builder'
import 'dynamic-form-builder/style.css'
</script>
<template>
<FormBuilder />
</template>FormRender — 表单渲染器
<script setup lang="ts">
import { ref } from 'vue'
import { FormRender } from 'dynamic-form-builder'
import type { FormConfig } from 'dynamic-form-builder'
import 'dynamic-form-builder/style.css'
const config: FormConfig = {
formId: 'my-form',
formMeta: { title: '示例', labelWidth: 100, labelPosition: 'right', labelSuffix: '', size: 'default', hideRequiredAsterisk: false },
items: [
{ compId: 'c1', type: 'input', label: '姓名', prop: 'name', commonProps: { placeholder: '请输入' }, typeProps: { clearable: true }, rules: [], visibilityRule: null, autoFill: null },
],
}
const formData = ref({})
</script>
<template>
<FormRender :config="config" v-model="formData" @submit="(d) => console.log(d)" />
</template>两大组件
本项目提供两个核心组件,分别用于设计阶段和运行阶段:
| 组件 | 用途 | 对应文件 |
|---|---|---|
| 🏗️ FormBuilder(表单设计器) | 拖拽搭建表单、配置属性、导出 JSON | src/App.vue(编排)、FormCanvas.vue、PropertyPanel.vue、ComponentPalette.vue |
| 📋 FormRender(表单渲染器) | 根据 JSON 配置直接渲染一个可用的、带验证的表单 | src/components/FormRender.vue |
高级功能示例
条件可见性
让"邮箱"字段仅在 notify 开关开启时才显示:
{
compId: 'c4',
type: 'input',
label: '通知邮箱',
prop: 'email',
// ...
visibilityRule: {
enabled: true,
topLogic: 'and',
groups: [
{
logic: 'and',
conditions: [
{ compId: 'c_notify', operator: 'eq', value: true },
],
},
],
},
}支持的运算符:eq neq gt lt gte lte in notIn empty notEmpty。
动态数据源
下拉选项从接口获取,支持 {{prop}} 模板替换:
typeProps: {
dataSource: {
mode: 'dynamic',
apiUrl: 'https://api.example.com/departments?q={{keyword}}',
method: 'GET',
labelKey: 'name',
valueKey: 'id',
},
}栅格布局
多个组件并排排列:
{
gridId: 'g1',
type: 'grid-row',
columns: [
{ colId: 'col1', span: 12, components: [ /* 占半行的组件 */ ] },
{ colId: 'col2', span: 12, components: [ /* 占半行的组件 */ ] },
],
}数据模型(FormConfig JSON 结构)
FormConfig
├── formId: string ← 表单唯一标识
├── formMeta: FormMeta ← 表单全局设置
│ ├── title ← 表单标题
│ ├── labelWidth ← 标签宽度(px)
│ ├── labelPosition ← "left" | "right" | "top"
│ ├── labelSuffix ← 标签后缀(如 ":")
│ ├── size ← "small" | "default" | "large"
│ └── hideRequiredAsterisk ← 是否隐藏必填星号
│
└── items: CanvasItem[] ← 组件列表(扁平数组)
├── FormComponent
│ ├── compId: string ← 组件唯一 ID
│ ├── type: ComponentType ← 18 种类型之一
│ ├── label: string ← 显示标签
│ ├── prop: string ← 表单字段名(v-model 绑定 key)
│ ├── commonProps ← 通用属性(placeholder, required, disabled...)
│ ├── typeProps ← 类型专属属性(options, format, rangeMode...)
│ ├── rules: FormRule[] ← 验证规则
│ ├── visibilityRule ← 条件可见性规则(AND/OR 逻辑组)
│ └── autoFill ← 自动填充规则(联动赋值)
│
└── GridRow ← 多列布局容器
├── gridId: string
├── type: "grid-row"
└── columns[] → { colId, span, components: FormComponent[] }