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

封装一个搜索区域 SearchForm.vue组件

父组件

<template><div><SearchForm:form-items="searchItems":initial-values="initialValues"@search="handleSearch"@reset="handleReset"><!-- 自定义插槽内容 --><template #custom-slot="{ form }"><el-inputv-model="form.customField"placeholder="自定义字段"></el-input></template><!-- 额外操作按钮 --><template #extra-actions><el-button type="warning" @click="handleExport">导出</el-button></template></SearchForm><!-- 其他页面内容 --></div>
</template><script>import SearchForm from '@/views/largeScreen/productionBusiness/components/searchForm.vue'export default {name: 'WorkOrderDetailList',components: { SearchForm },data() {return {initialValues: {name: '默认值',status: '1'},searchItems: [{label: '姓名',prop: 'name',type: 'input',placeholder: '请输入姓名'},{label: '状态',prop: 'status',type: 'select',options: [{ label: '启用', value: '1' },{ label: '禁用', value: '0' }]},{label: '创建日期',prop: 'createTime',type: 'date',dateType: 'daterange',valueFormat: 'yyyy-MM-dd'},{label: '自定义字段',prop: 'customField',type: 'slot',slotName: 'custom-slot'}]}},methods: {handleSearch(params) {console.log('搜索参数:', params)// 调用API获取数据},handleReset() {console.log('表单已重置')},handleExport() {console.log('导出操作')}}}
</script>

子组件

<template><div><el-formref="searchFormRef":model="formModel":inline="true":label-width="labelWidth"class="search-form"@submit.prevent="handleSearch"><!-- 动态渲染搜索表单项 --><template v-for="(item, index) in formItems"><!-- 输入框 --><el-form-item:key="index"v-if="item.type === 'input' || !item.type":label="item.label":prop="item.prop"><el-inputv-model="formModel[item.prop]":placeholder="item.placeholder || `请输入${item.label}`"clearable@keyup.enter="handleSearch"/></el-form-item><!-- 选择器 --><el-form-itemv-else-if="item.type === 'select'":label="item.label":prop="item.prop"><el-selectv-model="formModel[item.prop]":placeholder="item.placeholder || `请选择${item.label}`"clearablefilterablestyle="width: 100%"><el-optionv-for="opt in item.options":key="opt.value":label="opt.label":value="opt.value"/></el-select></el-form-item><!-- 日期选择器 --><el-form-itemv-else-if="item.type === 'date'":label="item.label":prop="item.prop"><el-date-pickerv-model="formModel[item.prop]":type="item.dateType || 'date'":placeholder="item.placeholder || `请选择${item.label}`":value-format="item.valueFormat || 'yyyy-MM-dd'"clearable/></el-form-item><!-- 日期范围选择器 --><el-form-itemv-else-if="item.type === 'daterange'":label="item.label":prop="item.prop"><el-date-pickerv-model="formModel[item.prop]"type="daterange":start-placeholder="item.startPlaceholder || '开始日期'":end-placeholder="item.endPlaceholder || '结束日期'":value-format="item.valueFormat || 'yyyy-MM-dd'"clearable/></el-form-item><!-- 自定义插槽 --><el-form-itemv-else-if="item.type === 'slot'":label="item.label":prop="item.prop"><slot :name="item.slotName" :form="formModel"></slot></el-form-item></template><!-- 操作按钮区域 --><el-form-item class="search-form-actions"><el-button type="primary" @click="handleSearch">搜索</el-button><el-button @click="handleReset">重置</el-button><slot name="extra-actions"></slot></el-form-item></el-form></div>
</template><script>export default {name: 'SearchForm',props: {// 表单配置项formItems: {type: Array,required: true,validator: (value) => {return value.every((item) => {return item.prop && item.label})}},// 初始值initialValues: {type: Object,default: () => ({})},// 标签宽度labelWidth: {type: String,default: '100px'}},data() {return {formModel: {}}},watch: {initialValues: {immediate: true,handler(val) {this.initFormModel(val)}}},methods: {// 初始化表单数据initFormModel(initialValues) {const defaultModel = {}this.formItems.forEach((item) => {defaultModel[item.prop] = initialValues[item.prop] ?? null})this.formModel = defaultModel},// 搜索事件handleSearch() {this.$emit('search', this.formModel)},// 重置表单handleReset() {this.$refs.searchFormRef.resetFields()this.$emit('reset')},// 获取表单数据getFormData() {return { ...this.formModel }},// 设置表单数据setFormData(data) {Object.keys(data).forEach((key) => {if (this.formModel.hasOwnProperty(key)) {this.formModel[key] = data[key]}})}}
}
</script><style lang="scss" scoped>
.search-form {margin-bottom: 20px;padding: 20px;background: #f5f7fa;border-radius: 4px;&-actions {float: right;margin-right: 0;}
}
</style>

 

 

相关文章:

  • 【项目】构建高性能多线程内存池:简化版 tcmalloc 实现指南
  • scoped+组件通信+props校验+记事本组件
  • 企业微信PC端 开启调试模式
  • 关于我的服务器
  • Python + 淘宝 API 开发实战:自动化采集商品详情与 SKU 数据清洗指南
  • Qt项目——串口调试助手
  • vite【详解】常用配置 vite.config.js / vite.config.ts
  • 数据库案例2--事务、视图和索引
  • Flowable进阶-网关、事件和服务
  • cout和printf的区别
  • 量子噪声模拟器是验证量子算法的鲁棒性
  • LVGL Animation Image(Animimg)控件详解
  • [特殊字符] 第 2 篇:快速上手 Framer Motion(实操入门)
  • vue学习笔记06
  • NLM格式与温哥华格式的区别与联系是什么?
  • 基于STM32、HAL库的TCA8418RTWR I/O扩展器驱动程序设计
  • 【3D文件】3D打印迪迦奥特曼,3D打印的迪迦圣像,M78遗迹管理局,5款不同的3D打印迪迦免费下载,总有一款适合你
  • vue + element-plus自定义表单验证(修改密码业务)
  • MySQL安装实战:从零开始搭建你的数据库环境
  • ANDON系统如何解决重工业车间的信息传递难题
  • 最高法典型案例:学生在校受伤,学校并非必然担责
  • 张又侠董军分别与印尼国防部长会见会谈
  • 三博脑科跌超10%:董事长遭留置立案,称控制权未变化,经营秩序正常
  • 4月语言学联合书单|法庭审判话语的态度表达及人际功能研究
  • 科普书单·新书|鸟界戏精观察报告
  • 隽逸不凡——北京画院藏近代篆刻家金城花鸟画赏析