# form-render **Repository Path**: childe-jia/form-render ## Basic Information - **Project Name**: form-render - **Description**: vue3 element plus 表单二次封装 - **Primary Language**: JavaScript - **License**: AGPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 2 - **Created**: 2023-09-22 - **Last Updated**: 2025-08-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 技术交流群 711368818 ## 遗留问题 :待解决 select 为 multiple 多选时 必须初始化空数组(在 elementplus v-model 初始化 updateValue 时 为空数组会触发校验) ## Introduction ### WHAT form-renderer 基于元素 element-plus,但不限于元素 element-plus 组件。在完全继承 element-plus 元素的 form 属性的基础上,进行了扩展。一些非表单组件或自定义组件,因此,用户可以使用一段 json 来呈现完整的表单。 ### WHY 在我们的日常开发中,有很多有表单的页面,通常表单结构相似,逻辑重复。el 表单呈现器没有复杂的逻辑。它只转换 JSON 来呈现表单项,节省了编写业务逻辑的时间和精力,并减少了重复代码。 ## Features - 用 json 呈现表单 - 支持与自定义组件集成 - 支持 updateForm 方法批量更新表单数据 - 支持 setOptions 方法,动态更改选择选项 - 内容支持 inputFormat、outputFormat、trim 以处理组件的输入和输出值 - 支持 v-model ## Links - [$attrs 和 $listeners (vue2&&vue3)](https://blog.csdn.net/qq_63358859/article/details/133699476?spm=1001.2014.3001.5501) - [vue2 与 vue3 函数式组件](https://blog.csdn.net/qq_63358859/article/details/133635120?spm=1001.2014.3001.5501) - [vue 2 与 vue3 获取模版引用 (ref)的区别](https://blog.csdn.net/qq_63358859/article/details/133532229?spm=1001.2014.3001.5501) - [vue2 与 vue3 v-model 的区别](https://blog.csdn.net/qq_63358859/article/details/133484380?spm=1001.2014.3001.5501) - [vue2 版本](https://blog.csdn.net/qq_63358859/article/details/130442636?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169684271816800180612618%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=169684271816800180612618&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-7-130442636-null-null.nonecase&utm_term=render&spm=1018.2226.3001.4450) - [中文文档](https://gitee.com/childe-jia/form-render/wikis/%E6%96%87%E6%A1%A3/%E4%BB%8B%E7%BB%8D) - [element-plus table 的封装](https://gitee.com/childe-jia/table-vue3) ## Quick Start ```ts pnpm i el-form-renderer-vue3 ``` ```ts import elFormRenderer from "el-form-renderer-vue3"; app.use(elFormRenderer); ``` ```ts ``` ## Props ```ts export default { // ... props: { /** * support all el-form's props * @see: https://element.eleme.io/#/zh-CN/component/form#form-attributes */ /** * 表单项的配置数组,每个表单项代表一个原子表单项 * the form config's array, each item represents a form-item */ content: { type: Array, // type:Content[], check Content's definition below required: true }, /** * disable all form-items */ disabled: { type: Boolean, default: false } } } /** * 表单项的typescript定义 * 支持所有el-form-item's props。表单项组件本身的props定义在el上 * definition of form-item written in typescript. * support all el-form-item's props. The component's props need to be set at prop el */ interface Content { // 每一个原子都存在 id,用于存储该原子的值,不能重复 // key of form-item value in form value. Must be unique id: string /** * 可以是element提供的所有表单组件类型,如传入'input',则渲染出'el-input' * 当type="group"时,可以创造复杂对象类型的表单数据,配合items使用。此时getFormValue()返回的是对象类型的数据,对象的每个属性对应items里的每一项 * support all element's form component, e.g., type 'input' will render as 'el-input'. * you can create nested form value with type 'group' and use items to define that form value's shape. The type of this form value will be 'object' */ type: string /** * 当type="group"时使用 * items内依然遵循同一层级的id不重复的原则 * using with type 'group' * the `id` in each item of items must be unique */ items: Content[] /** * 默认值 * FIXME: 别用关键字做 key */ default?: any /** * 当 type === 'input' 时展示文本值 * 当 type === 'select' 时展示对应 label * 对于其他组件等同于 disabled = true */ readonly = false /** * @deprecated */ enableWhen?: object | string /** * 传入一个方法,并返回 boolean,返回 true 时则隐藏该表单项 * formValue 为当前 form 的值,item 为当前表单项的定义 * hide the form-item when return true * formValue is same as what getFormValue returns, and item is the config of this form-item */ hidden?: (formValue: Object, item: Content) => boolean /** * 具有选择功能的原子表单可用此定义可选项 * use with type: select, radio-group, radio-button, checkbox-group, checkbox-button */ options?: {label: string; value?: any}[] /** * 配置remote.url,即可远程配置组件的某个prop! * remote接受以下属性: * url: 远程接口的地址 * prop: 要注入的 prop 的名称,默认为 options * request: 可选,请求方法 * dataPath: 可选,data在响应体中的路径 * onResponse: 可选,处理请求回来的数据 * onError: 可选,处理请求出错的情况 * 另外,针对 select、radio-group、checkbox-group,远程数据能自动映射成 el-option 选项!以下属性仅在此情况使用 * label: 可选,可直接配置远程数据中用作 label 的key * value: 可选,可直接配置远程数据中用作 value 的key * @see https://zhuanlan.zhihu.com/p/97827063 * * use remote to set one prop! remote accept following props: * url: remote api address * prop: prop name that data inject * request: optional, customize how to get your options * dataPath: optional, data's path in response * onResponse: optional, deal with your response * onError: optional, deal with request error * and, we treat select、radio-group、checkbox-group specially and the resp will be map as an el-option's group! following props only suitable for this case * label: optional, label key in resp * value: optional, value key in resp */ remote?: { url: string request = () => this.$axios.get(url).then(resp => resp.data) prop = 'options' dataPath = '' onResponse = resp => { if (dataPath) resp = _get(resp, dataPath) switch (this.data.type) { case 'select': case 'checkbox-group': case 'radio-group': return resp.map(item => ({ label: item[label], value: item[value] })) default: return resp } } onError = error => console.error(error.message) label = 'label' value = 'value' } attrs?: object // html attributes /** * 用于定义具体原子表单(如el-input)的属性,比如定义el-input的placeholder * use to define props of the actual component of this form-item, such as placeholder of el-input */ el?: object /** * 使用自定义组件 * component适用于渲染局部注册组件和自定义组件,而type适用于带el-前缀的全局组件 * custom component * use it when element's form components are not enough */ component?: Vue /** * 是否覆盖自定义组件内置的校验规则 * `true` 为覆盖, 默认为 `false` * whether to override the validation rules written in custom components * `true` to override, default `false` */ overrideRules: boolean label?: string //set el-form-item's label trim = true // trim value at change event // 用于处理输入值,输入的值包括:1. default;2. v-model;3. updateForm。参数为整个表单的值对象或 updateForm 传入的对象 // 如果 inputFormat 返回 undefined,则不会更新此表单项 // obj is param you passed to updateForm. You can use this function to hijack this process and customize the form value inputFormat?: (obj: any) => any // 用于处理输出值,参数为对应组件返回值 // 如果处理后的值是对象类型,会覆盖(Object.assign)到整个表单的值上 // used to hijack the getFormValue's process and customize the return value outputFormat?: (val: any) => any // set el-form-item's rules rules?: object // @deprecated atChange?: (id: string, value: any) => void /** * 监听表单项发出的事件 * listen to any events emitted by component of form item * @param {any[]} args - what that event emits * @param {function} updateForm - same as methods.updateForm */ on?: { [eventName: string]: (args: any[], updateForm: function) => void } } /** * a tour of typescript */ interface obj { a: string // type string b?: string // type string, optional c = true // type boolean, optional, default true d: string[] // type array, each item must be string e: any // could be any valid js type f: (a: number) => void // type function, which receives a param 'a' as number and return nothing h: Vue // instance of Vue i: {[a: string]: number} // type object, whose key is type string, and value is type number } ``` ## Methods support all [el-form's methods](https://element.eleme.io/#/zh-CN/component/form#form-methods) ## Slots | Slot | Description | | -------- | ------------------------------------------- | | default | insert at bottom | | id:hello | insert before form-item whose id is 'hello' | ## Inspiration thanks to [el-form-renderer](https://github.com/femessage/el-form-renderer/)