当前位置: 首页 > news >正文

Vue3 通过json配置生成查询表单

功能实现背景

通过Vue3实现后台管理项目一定含有表格功能,通常离不开表单。于是通过json配置来生成表单的想法由然而生

注意:
1.项目依赖element-plus

使用规则
1. 组件支持使用v-model管理值,当v-model不配置时也可以通过@finish事件获取表单值
2. 当FormRender组件设置v-model后,schema配置项中defaultValue设置的默认值无效
3. 项目默认查询和重置事件,也支持插槽自定义事件
4. 通过插槽自定义事件时,可以通过插槽获取表单值,也可以通过组件暴露属性和方法获取el-form属性&方法和表单值

项目代码

  1. 创建type/index.ts文件
import { type Component } from 'vue'export type ObjAny = { [T: string]: any }
export interface SchemaItem {key: string // 唯一标识 & 表单项v-model的属性label: string // form-item 的label属性type?: 'input' | 'select' // 支持 el-input 和 el-select组件defaultValue?: any // 当组件未配置v-model属性,可自定义默认值component?: Component // 自定义组件props?: { [K: string]: any } // 组件属性:继承el-form表单组件属性
}
  1. 创建FormRender.vue文件
<template><el-form ref="formRef" :model="dataForm" :inline="true"><el-form-item v-for="item in schema" :key="item.key" :label="item.label" :prop="item.key"><!-- 自定义组件 --><template v-if="item.component"><component :is="item.component" v-bind="item.props" v-model="dataForm[item.key]" /></template><!-- el-select --><template v-else-if="item.type === 'select'"><el-select v-bind="item.props" v-model="dataForm[item.key]" /></template><!-- 默认: el-input --><template v-else><el-input v-bind="item.props" v-model="dataForm[item.key]" /></template></el-form-item><!-- 事件插槽,默认查询和重置功能,支持自定义 --><slot name="handle" :data="{ ...dataForm }"><el-form-item v-if="showFinish || showReset"><el-button v-if="showFinish" :loading="loading" type="primary" @click="handleClick">{{ textFinish }}</el-button><el-button v-if="showReset" type="primary" @click="handleReset">{{ textReset }}</el-button></el-form-item></slot></el-form>
</template><script setup lang="ts">
import type { FormInstance } from 'element-plus'
import { reactive, useTemplateRef } from 'vue'
import {ObjAny, SchemaItem} from 'type/index.ts'defineOptions({name: 'FormRender'
})const props = withDefaults(defineProps<{showFinish?: booleanshowReset?: booleantextFinish?: stringtextReset?: stringschema: SchemaItem[]}>(),{showFinish: true,showReset: true,textFinish: '查询',textReset: '重置'}
)
const emit = defineEmits<{(e: 'finish', data: ObjAny): void(e: 'reset', data: ObjAny): void
}>()const dataForm = defineModel() as ObjAny
const loading = defineModel('loading', { type: Boolean, default: false })
const formRef = useTemplateRef<FormInstance | null>('formRef')initForm()/*** 当组件未定义 v-model,内部生成form data*/
function initForm() {if (dataForm.value === undefined) {const defaultForm: { [T: string]: any } = reactive({})props.schema.forEach(item => {defaultForm[item.key] = item.defaultValue || ''})if (dataForm.value === undefined) {dataForm.value = defaultForm}}
}
/*** finish*/
function handleClick() {emit('finish', { ...dataForm.value })
}/*** reset*/
function handleReset() {formRef.value?.resetFields()emit('reset', { ...dataForm.value })
}
// 默认暴露的属性和方法,可自行添加
defineExpose({elFormInstance: formRef,reset: handleReset
})
</script>

案例

  1. 简单渲染和取值:未使用v-model
<FormRender :schema="schema" @finish="handleSubmit" /><script lang="ts" setup>
import FormRender from './FormRender.vue'
import {ElInput} from 'element-plus'
import {ref, onMounted, computed} from 'vue'
import {ObjAny, SchemaItem} from 'type/index.ts'const options = ref<{ label: string; value: string }[]>([])
// 默写数据需要通过网络请求获取,所有需要使用到 computed
const schema = computed<SchemaItem[]>(() => [{key: 'content',label: '名称',type: 'input',defaultValue: '张三',props: {placeholder: '请输入名称',clearable: true,style: {width: '200px'}}},{key: 'orderNo',label: '订单号',defaultValue: '20250012',component: ElInput,props: {placeholder: '请输入订单号',clearable: true,style: {width: '200px'}}},{key: 'state',label: '状态',type: 'select',props: {placeholder: '请选择状态',clearable: true,options: options.value,style: {width: '200px'}}}
])function handleSubmit(value: ObjAny) {console.log(value)
}
onMounted(() => {// 模拟网络请求数据options.value = [{value: '1',label: 'Option1'},{value: '2',label: 'Option2'},{value: '3',label: 'Option3'}]
})
</script>
  1. 使用v-model
<FormRender v-model='data' :schema="schema" @finish="handleSubmit" /><script lang="ts" setup>
import FormRender from './FormRender.vue'
import {ElInput} from 'element-plus'
import {ref, onMounted, computed} from 'vue'
import {ObjAny, SchemaItem} from 'type/index.ts'const data = ref({content: '张三',orderNo: '20250012',state: ''
})
const options = ref<{ label: string; value: string }[]>([])
// 默写数据需要通过网络请求获取,所有需要使用到 computed
// 当使用v-model时, defaultValue值将失效
const schema = computed<SchemaItem[]>(() => [{key: 'content',label: '名称',type: 'input',props: {placeholder: '请输入名称',clearable: true,style: {width: '200px'}}},{key: 'orderNo',label: '订单号',component: ElInput,props: {placeholder: '请输入订单号',clearable: true,style: {width: '200px'}}},{key: 'state',label: '状态',type: 'select',props: {placeholder: '请选择状态',clearable: true,options: options.value,style: {width: '200px'}}}
])function handleSubmit(value: ObjAny) {console.log(value)
}
onMounted(() => {// 模拟网络请求数据options.value = [{value: '1',label: 'Option1'},{value: '2',label: 'Option2'},{value: '3',label: 'Option3'}]
})
</script>
  1. 使用slot自定义事件
<FormRender ref="formRenderRef" v-model='data' :schema="schema"><template v-slot:handle="{ data }"><el-form-item><el-button type="primary" @click="handleSubmit(data)">查询</el-button><el-button @click="handleReset">重置</el-button></el-form-item></template>
</FormRender><script lang="ts" setup>
import FormRender from './FormRender.vue'
import {ElInput} from 'element-plus'
import {ref, onMounted, computed} from 'vue'
import {ObjAny, SchemaItem} from 'type/index.ts'const formRenderRef = useTemplateRef('formRenderRef')const data = ref({content: '张三',orderNo: '20250012',state: ''
})
const options = ref<{ label: string; value: string }[]>([])// 默写数据需要通过网络请求获取,所有需要使用到 computed
// 当使用v-model时, defaultValue值将失效
const schema = computed<SchemaItem[]>(() => [{key: 'content',label: '名称',type: 'input',props: {placeholder: '请输入名称',clearable: true,style: {width: '200px'}}},{key: 'orderNo',label: '订单号',component: ElInput,props: {placeholder: '请输入订单号',clearable: true,style: {width: '200px'}}},{key: 'state',label: '状态',type: 'select',props: {placeholder: '请选择状态',clearable: true,options: options.value,style: {width: '200px'}}}
])function handleSubmit(value: ObjAny) {console.log(value)
}
const handleReset = () => {formRenderRef.value?.reset()
}
onMounted(() => {// 模拟网络请求数据options.value = [{value: '1',label: 'Option1'},{value: '2',label: 'Option2'},{value: '3',label: 'Option3'}]
})
</script>

文章转载自:

http://hYl8FHpH.zzqgc.cn
http://1KBTRS3Z.zzqgc.cn
http://2m7vpTFy.zzqgc.cn
http://4xoQBTXP.zzqgc.cn
http://lP8tmxRi.zzqgc.cn
http://UJw2kPoj.zzqgc.cn
http://Jaaww2vG.zzqgc.cn
http://zN0ZMjpV.zzqgc.cn
http://7tgMaktb.zzqgc.cn
http://GnnXFzlk.zzqgc.cn
http://IC0CKZNP.zzqgc.cn
http://m5w3LkEI.zzqgc.cn
http://GqVC9tXr.zzqgc.cn
http://xaucFqei.zzqgc.cn
http://UgZgzPv2.zzqgc.cn
http://h1h8llZa.zzqgc.cn
http://ivWRq1ui.zzqgc.cn
http://W2sFU1gt.zzqgc.cn
http://U4P5AEVp.zzqgc.cn
http://4d57ZoOq.zzqgc.cn
http://ycqSc6kS.zzqgc.cn
http://v1IrhGCq.zzqgc.cn
http://kH6Ps5B8.zzqgc.cn
http://mb6pjqpr.zzqgc.cn
http://5ivbzv9z.zzqgc.cn
http://aOvcrcz3.zzqgc.cn
http://QiaHHrn1.zzqgc.cn
http://AxdBc5Lc.zzqgc.cn
http://aInGQ2rt.zzqgc.cn
http://LGshnsOU.zzqgc.cn
http://www.dtcms.com/a/382262.html

相关文章:

  • spring 声明式事务
  • [硬件电路-190]:三极管的电流放大特性看男女关系3:过渡的投入,输出进入不安全区、疲惫期,反而双方系统造成伤害
  • json文件转excel
  • ros2获取topic信息解析
  • C++中的贪心算法
  • 【Selenium】Selenium 测试失败排查:一次元素定位超时的完整解决之旅
  • Selenium 使用指南
  • 【Python 入门】(2)Python 语言基础(变量)
  • XSS攻击1----(XSS介绍)
  • 【LeetCode 每日一题】3446. 按对角线进行矩阵排序——(解法一)分组 - 排序 - 重建
  • 【亲测有效】解决 “Batch script contains DOS line breaks (\r\n)” 报错
  • 集值优化问题:理论、应用与前沿进展
  • 17、逻辑回归与分类评估 - 从连续到离散的智能判断
  • AMD KFD的BO设计分析系列3-1: GTT的实现分析
  • 如何实现静态库与动态库的制作
  • 【硬件开发】电源抑制比PSRR
  • 基于Redisson的分布式锁原理深度解析与性能优化实践指南
  • 【Leetcode hot 100】101.对称二叉树
  • 破解多校区高校运维困局,协同效率提升60%的智能运维方案
  • 王道计算机组成原理 学习笔记
  • Matplotlib:绘制你的第一张折线图与散点图
  • 即梦批量生成图片软件使用运营大管家-即梦图片批量生成器
  • Qt中解析JSON文件
  • 从静态表查询冲突到其原理
  • Git 版本回退与撤销修改
  • Tcpdump: The Basics Tcpdump 基础
  • 智慧物联网水利大数据平台建设方案PPT(70页)
  • 字典树初步
  • GitHub 热榜项目 - 日榜(2025-09-13)
  • 18、决策树与集成学习 - 从单一智慧到群体决策