npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mzm-auto-form

v1.2.5

Published

基于vue3、element-plus、typeScript实现的数据驱动式动态表单组件

Readme

mzm-auto-form

基于 Vue3、Element-Plus、TypeScript 实现的数据驱动式动态表单组件。旨在通过 JSON 配置的方式快速构建复杂表单。

特性

  • 🚀 数据驱动: 完全通过配置对象渲染表单,摆脱冗长的 HTML 模板。
  • 📦 开箱即用: 内置丰富的表单控件类型(输入框、选择器、日期、开关、上传等)。
  • 🔗 响应式联动: 支持基于 formData 状态的动态显示/隐藏、动态禁用、动态校验规则与动态选项列表。
  • 🎯 完美兼容 Element Plus: 继承 el-form 及内部控件的所有属性与事件,支持插槽注入。
  • 🤖 大模型友好 (LLM-Friendly): 提供了清晰的 TypeScript 接口定义,方便在通过 AI 生成代码时保持严格的类型约束。

安装

npm i mzm-auto-form

引入

1. 全局注册 (main.ts)

import { createApp } from "vue";
import App from "./App.vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";

import MzmAutoForm from "mzm-auto-form";
import "mzm-auto-form/lib/index.css";

const app = createApp(App);
app.use(ElementPlus);
app.use(MzmAutoForm);
app.mount("#app");

2. 局部引入 (在组件中)

import { mzmAutoForm } from "mzm-auto-form";
import "mzm-auto-form/lib/index.css";

基础用法

通过定义 configList 数组即可快速渲染表单:

<template>
	<mzm-auto-form
		ref="formRef"
		:config-list="formConfig"
		label-width="120px"
		@loaded="handleLoaded"
	>
		<!-- 自定义插槽内容 -->
		<template #customSlot="{ formData, formItem }">
			<el-button @click="formData[formItem.key] = 'custom'">
				自定义按钮:{{ formData[formItem.key] }}
			</el-button>
		</template>
	</mzm-auto-form>

	<el-button
		type="primary"
		@click="submit"
		>提交</el-button
	>
</template>

<script setup lang="ts">
import { ref } from "vue";
import {
	mzmAutoForm,
	AutoFormItemType,
	type AutoFormItem,
} from "mzm-auto-form";
import "mzm-auto-form/lib/index.css";

const formRef = ref<InstanceType<typeof mzmAutoForm>>();

const formConfig = ref<AutoFormItem[]>([
	{
		key: "username",
		type: AutoFormItemType.Input,
		formItemProps: { label: "用户名" },
		props: { placeholder: "请输入用户名", clearable: true },
		rules: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
	},
	{
		key: "role",
		type: AutoFormItemType.Select,
		formItemProps: { label: "角色" },
		options: [
			{ label: "管理员", value: "admin" },
			{ label: "普通用户", value: "user" },
		],
	},
	{
		key: "customField",
		slotName: "customSlot",
		formItemProps: { label: "自定义插槽" },
	},
]);

const handleLoaded = (formData: any) => {
	console.log("表单加载完成,初始数据:", formData);
};

const submit = async () => {
	// 获取 element-plus 的 el-form 实例并校验
	await formRef.value?.formRef?.validate();
	// 获取组装好的表单数据(自动剔除 isHide 为 true 的字段)
	const data = formRef.value?.getFormData();
	console.log("提交数据:", data);
};
</script>

API 文档

组件属性 (Props)

除了支持 Element-Plus el-form 的所有原生属性外,还支持:

| 属性名 | 说明 | 类型 | 默认值 | | ------------ | ------------------------------------------ | ---------------- | ------ | | configList | 表单项配置列表(核心),详情见下文接口定义 | AutoFormItem[] | [] |

组件事件 (Emits)

| 事件名 | 说明 | 回调参数 | | --------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------- | | loaded | 表单初始化完成(默认值已挂载)时触发 | (formData: Record<string, any>) => void | | {customEvent} | 通过 eventsIn 注入的事件抛出 | (eventObj: any, formData: any, itemConfig: AutoFormItem, configList: AutoFormItem[]) => void |

暴露方法 (Exposes)

通过组件的 ref 可调用以下方法/属性:

| 方法名/属性名 | 说明 | 类型 | | --------------- | -------------------------------------------------------------------- | --------------------------- | | getFormData() | 获取当前表单数据(自动剔除 isHide 为 true 的字段数据) | () => Record<string, any> | | resetForm() | 重置表单到初始状态(重新挂载默认值) | () => void | | formRef | 获取原生的 Element Plus el-form 实例,可用于调用 validate 等方法 | Ref<FormInstance> |


TypeScript 类型定义 (大模型生成必读规范)

mzm-auto-form 依赖高度抽象的配置项。当通过 AI 或手动生成代码时,请严格参考并遵循以下 AutoFormItemAutoFormItemType 接口定义,保证配置的正确性与类型安全。

AutoFormItem 接口定义

export interface AutoFormItem {
	/** 表单项绑定字段名 (唯一标识) */
	key?: string;

	/** 是否隐藏当前项(隐藏后不仅不渲染,getFormData 也不会返回该字段) */
	isHide?:
		| boolean
		| ((formData: Record<string, any>, formItem: AutoFormItem) => boolean);

	/** 是否禁用当前项控件 */
	isDisabled?:
		| boolean
		| ((formData: Record<string, any>, formItem: AutoFormItem) => boolean);

	/** 控件类型枚举,参考 AutoFormItemType */
	type?: AutoFormItemType;

	/** 控件默认值,支持直接赋值或函数返回(支持 Promise) */
	defaultValue?: any | (() => any);

	/** el-form-item 包装层的配置属性 (如 label, label-width 等) */
	formItemProps?: Record<string, any>;

	/** 表单项验证规则,兼容 Element Plus 规则,支持动态返回 */
	rules?:
		| Record<string, any>
		| ((
				formData: Record<string, any>,
				formItem: AutoFormItem,
		  ) => Record<string, any>);

	/** 内部真实控件 (如 el-input) 的属性配置 */
	props?: Record<string, any>;

	/** select/radio/checkbox 等控件的选项列表,支持动态异步获取 */
	options?:
		| { label: string; value: any }[]
		| ((
				formData: Record<string, any>,
				formItem: AutoFormItem,
				configList: AutoFormItem[],
		  ) =>
				| { label: string; value: any }[]
				| Promise<{ label: string; value: any }[]>);

	/** 绑定到控件上的事件对象 (原生) */
	events?: Record<string, Function>;

	/** 事件注入:将控件的事件转发抛出给外层组件的 @[emitName] 事件 */
	eventsIn?: { innerName: string; emitName: string }[];

	/** 输入框后缀单位文本(仅对 Input 等部分非文本域控件生效) */
	valueUnit?: any;

	/** 表单项底部描述文本 */
	describe?: string;

	/** 表单控件内部插槽配置,映射外层插槽到控件内 */
	internalSlots?: { innerName: string; slotName: string }[];

	/** 初始化数据格式化钩子 */
	defaultValueFormatter?: (
		defaultValue: any,
		itemConfig: AutoFormItem,
	) => any;

	/** 提交前数据格式化钩子 */
	valueFormatter?: (
		value: any,
		formData: Record<string, any>,
		itemConfig: AutoFormItem,
	) => any;

	/** 自定义整个表单项控件内容的插槽名(优先级高于 type,会替代内置控件) */
	slotName?: string;

	/** 开发者自定义存储的额外配置数据,组件不消费此字段 */
	otherData?: any;
}

AutoFormItemType 控件类型枚举

支持丰富的内置控件,使用时推荐引入 AutoFormItemType 进行类型安全的赋值。

export enum AutoFormItemType {
	Input = "el-input", // 输入框
	InputNumber = "el-input-number", // 数字步进器
	InputTag = "el-input-tag", // 标签输入框
	ColorPickerPanel = "el-color-picker-panel", // 颜色选择器
	Slider = "el-slider", // 滑块
	Select = "el-select", // 下拉选择器
	SelectTree = "el-tree-select", // 树形下拉选择器
	Radio = "el-radio-group", // 单选框组
	RadioButton = "el-radio-group_button", // 按钮样式单选框组
	Checkbox = "el-checkbox", // 复选框组
	DatePicker = "el-date-picker", // 日期选择器
	TimePicker = "el-time-picker", // 时间选择器
	Switch = "el-switch", // 开关
	Cascader = "el-cascader", // 级联选择器
	Upload = "mzm-upload", // 文件上传 (内置定制版)
}

进阶用法示例

1. 动态表单联动 (显隐与禁用)

可以通过传入函数实现复杂的动态联动,函数参数会自动注入当前表单的完整数据 formData

{
  key: 'reason',
  type: AutoFormItemType.Input,
  formItemProps: { label: '退回原因' },
  // 当 status 为 reject 时才显示
  isHide: (formData) => formData.status !== 'reject',
  // 动态验证规则
  rules: (formData) => {
    return formData.status === 'reject'
      ? [{ required: true, message: '请填写退回原因' }]
      : [];
  }
}

2. 异步拉取选项列表 (Options)

options 支持返回一个 Promise,组件会自动在内部等待并渲染,适用于需要调用后端接口获取字典的场景。

{
  key: 'userId',
  type: AutoFormItemType.Select,
  formItemProps: { label: '选择用户' },
  options: async (formData, item) => {
    // 模拟后端接口请求
    const res = await fetchUserList(formData.departmentId);
    return res.data.map(user => ({ label: user.name, value: user.id }));
  }
}

3. 级联面板 (Cascader) 的使用

级联面板组件在配置 options 时,需要传入符合 CascaderOption 规范的多层级数组。mzm-auto-form 内部已经自动处理了其选项挂载及 label 的渲染插槽逻辑。

{
  key: 'region',
  type: AutoFormItemType.Cascader,
  formItemProps: { label: '所属区域' },
  props: {
    // Cascader 的原生配置项
    props: {
      expandTrigger: 'hover',
      value: 'code',
      label: 'name'
    },
    placeholder: '请选择所在区域',
    clearable: true
  },
  // 可以是同步的树形数据,也可以是异步请求获取
  options: [
    {
      code: 'zhejiang',
      name: '浙江',
      children: [
        { code: 'hangzhou', name: '杭州' },
        { code: 'ningbo', name: '宁波' }
      ]
    },
    {
      code: 'jiangsu',
      name: '江苏',
      children: [
        { code: 'nanjing', name: '南京' }
      ]
    }
  ]
}

4. 文件上传 (Upload) 的使用

mzm-auto-form 内置了深度定制的文件上传组件 (mzm-upload),支持图片预览、列表管理、单文件/多文件控制,同时允许动态获取 Token 和上传参数。

它的返回值 modelValue 默认支持两种类型:

  • 单文件 (默认 limit: 1):返回 URL 字符串
  • 多文件 (limit > 1):返回逗号分隔的 URL 字符串 或 字符串数组。

关键专属属性 (props):

  • action (string): 必填,上传的服务器地址 (同 Element Plus)。
  • uploadType ('file' | 'image'): 上传样式类型,默认 file,设置为 image 会展示照片墙模式。
  • limit (number): 最大允许上传个数,默认 1。
  • resolveResponse (Function): 核心钩子,用于从接口返回的数据中提取文件 URL 赋值给表单。
  • headers / data / accept: 均支持直接传对象/字符串,或传入 动态函数 (formData, formItem) => value
  • baseUrl (string): 拼接在返回的 URL 前的域名前缀(多用于相对路径处理)。
{
  key: 'avatar',
  type: AutoFormItemType.Upload,
  formItemProps: { label: '用户头像' },
  props: {
    action: '/api/upload', // 接口地址
    uploadType: 'image',   // 使用图片墙模式
    limit: 1,              // 限制1张
    tip: '只能上传 jpg/png 文件,且不超过 2MB',

    // 动态获取 Token 等请求头
    headers: (formData, item) => ({
      Authorization: `Bearer ${localStorage.getItem('token')}`
    }),

    // 动态附带额外的表单数据
    data: (formData) => ({
      userId: formData.id,
      fileType: 'avatar'
    }),

    // 核心:提取服务端返回的实际 URL 给到 formData.avatar
    // 假设服务端返回: { code: 200, data: { fileUrl: 'https://xxx.png' } }
    resolveResponse: (response) => {
      return response.data?.fileUrl || '';
    }
  }
}

5. 事件绑定与事件注入 (events vs eventsIn)

组件支持两种方式来处理表单控件内部抛出的原生事件(如 changeblurfocus 等),它们在适用场景和代码结构上有所不同:

(1) events:直接绑定(内联回调)

通过 events 对象,你可以直接在配置项中为控件绑定回调函数。 适用场景:适合处理简单的内部逻辑或调试,不需要将事件与外部 Vue 组件的方法解耦。

参数说明: 在 events 中定义的回调函数,接收四个参数:(formData, itemConfig, configList, args)

  • formData: 当前表单的全量响应式数据对象
  • itemConfig: 当前表单项的配置对象
  • configList: 完整的表单配置列表
  • args: 底层组件原生事件抛出的参数数组(例如 change 事件抛出的值会作为 args[0]
{
  key: 'username',
  type: AutoFormItemType.Input,
  formItemProps: { label: '用户名' },
  events: {
    // 监听 el-input 的 blur 事件
    blur: (formData, itemConfig, configList, args) => {
      console.log('用户名输入框失焦', args[0]); // args[0] 通常是原生 event 对象
    },
    // 监听 el-input 的 change 事件
    change: (formData, itemConfig, configList, args) => {
      console.log('值发生改变:', args[0]); // args[0] 是输入的新值
      // 直接在此处修改 formData 中的其他值
      formData.otherField = '联动值';
    }
  }
}

(2) eventsIn:事件注入(向外抛出)

如果在事件触发时需要调用外部组件的复杂方法(例如触发外层的响应式修改、请求其他接口等),直接在 JSON 配置里写函数会导致代码耦合严重或难以获取 Vue 上下文(如访问不到外部的 ref 变量)。 此时可以使用 eventsIn,将控件的内部事件转发并作为自定义事件抛出<mzm-auto-form> 的外层监听。

  • innerName: 控件原生触发的事件名(如 change)。
  • emitName: 转发给 <mzm-auto-form> 抛出的自定义事件名。

    注意: 如果 eventseventsIn 存在监听同一个内部事件发生冲突,默认以 eventsIn 优先级更高。

适用场景:适合将业务逻辑集中在 Vue 模板 <script setup> 内统一管理,保持表单配置 JSON 的纯粹性。

参数说明: 抛出到外层的自定义事件回调函数,接收四个参数:(eventArgs, formData, itemConfig, configList)

  • eventArgs: 底层组件原生事件抛出的参数数组(即包含原生抛出的所有参数,如 [val, event]
  • formData: 当前表单的全量数据
  • itemConfig: 当前表单项的配置
  • configList: 完整的表单配置列表

示例:

<template>
	<mzm-auto-form
		:config-list="formConfig"
		@on-city-change="handleCityChange"
	/>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { AutoFormItemType, type AutoFormItem } from "mzm-auto-form";

const formConfig = ref<AutoFormItem[]>([
	{
		key: "city",
		type: AutoFormItemType.Select,
		formItemProps: { label: "城市" },
		options: [
			{ label: "北京", value: "beijing" },
			{ label: "上海", value: "shanghai" },
		],
		eventsIn: [
			{
				innerName: "change", // 监听底层 el-select 的 change 事件
				emitName: "on-city-change", // 转发为 on-city-change 事件向外 emit
			},
		],
	},
]);

// 在外部组件中统一处理复杂的业务逻辑
// 接收参数为固定格式:(eventArgs: any[], formData: any, itemConfig: AutoFormItem, configList: AutoFormItem[])
const handleCityChange = (
	eventArgs: any[],
	formData: any,
	itemConfig: AutoFormItem,
	configList: AutoFormItem[],
) => {
	const selectedValue = eventArgs[0]; // 获取 el-select 抛出的第一个参数(选中的值)
	console.log("当前选中的城市值:", selectedValue);
	console.log("当前表单全量数据:", formData);

	// 可以在这里无缝访问外部的 Vue 响应式变量或调用接口
	// fetchCityArea(selectedValue).then(...)
};
</script>