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

Vue2 + Element UI 实战:手把手教你封装一个高复用的 SearchForm 搜索组件

前言 👋

在后台管理系统中,搜索区域(SearchForm)​ 几乎存在于每一个列表页中。

如果不加以封装,你的代码可能会变成这样:

<el-form :inline="true" :model="queryParams"> <el-form-item label="用户名"> <el-input v-model="queryParams.username" placeholder="请输入"></el-input> </el-form-item> <el-form-item label="状态"> <el-select v-model="queryParams.status" placeholder="请选择"> <el-option label="启用" value="1"></el-option> <el-option label="禁用" value="0"></el-option> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">搜索</el-button> <el-button @click="resetQuery">重置</el-button> </el-form-item> </el-form>

问题很明显

  • 😩 每个页面都要复制粘贴

  • 😩 样式、布局难以统一

  • 😩 新增/修改搜索项极其繁琐

今天,我们就来解决这个痛点,封装一个高内聚、低耦合SearchForm组件!


一、设计目标 🎯

我们要封装的组件需要具备以下特性:

  1. 配置驱动:通过一个config数组即可生成表单项。

  2. 内置类型:支持inputselectdatedaterange等常用类型。

  3. 自动双向绑定:无需手动v-model

  4. 一键重置:内置重置逻辑。

  5. 高度可定制:支持传入el-form-item的任意原生属性。


二、组件实现 (src/components/SearchForm/index.vue) ⚙️

这是我们的核心代码,请仔细看注释。

<template> <el-form ref="searchFormRef" :inline="true" :model="model" :label-width="labelWidth" class="search-form" > <template v-for="(item, index) in config"> <!-- 输入框 --> <el-form-item v-if="item.type === 'input'" :key="index" :label="item.label" :prop="item.prop" > <el-input v-model="model[item.prop]" :placeholder="item.placeholder || '请输入'" :clearable="item.clearable ?? true" :style="{ width: item.width || '200px' }" /> </el-form-item> <!-- 下拉框 --> <el-form-item v-else-if="item.type === 'select'" :key="index" :label="item.label" :prop="item.prop" > <el-select v-model="model[item.prop]" :placeholder="item.placeholder || '请选择'" :clearable="item.clearable ?? true" :style="{ width: item.width || '200px' }" > <el-option v-for="opt in item.options" :key="opt.value" :label="opt.label" :value="opt.value" /> </el-select> </el-form-item> <!-- 日期选择器 --> <el-form-item v-else-if="item.type === 'date'" :key="index" :label="item.label" :prop="item.prop" > <el-date-picker v-model="model[item.prop]" :type="item.dateType || 'date'" :placeholder="item.placeholder || '请选择日期'" :value-format="item.valueFormat || 'yyyy-MM-dd'" :style="{ width: item.width || '200px' }" /> </el-form-item> </template> <!-- 操作区 --> <el-form-item class="search-buttons"> <el-button type="primary" icon="el-icon-search" @click="handleSearch"> 搜索 </el-button> <el-button icon="el-icon-refresh" @click="handleReset"> 重置 </el-button> <!-- 插槽,用于扩展按钮 --> <slot /> </el-form-item> </el-form> </template> <script> export default { name: 'SearchForm', props: { // 搜索配置数组 config: { type: Array, required: true, default: () => [] }, // 搜索参数对象 (v-model) model: { type: Object, required: true }, // label宽度 labelWidth: { type: String, default: '80px' } }, methods: { // 触发父组件的搜索事件 handleSearch() { this.$emit('search') }, // 重置表单 handleReset() { this.$refs.searchFormRef.resetFields() // 重置后自动触发一次搜索 this.$emit('search') } } } </script> <style scoped lang="scss"> .search-form { background-color: #fff; padding: 18px 20px 0; border-radius: 4px; margin-bottom: 16px; .search-buttons { margin-bottom: 18px; } } </style>

三、如何使用?只需 3 步 🚀

Step 1:引入并注册组件

// 在页面组件中 import SearchForm from '@/components/SearchForm/index.vue' export default { components: { SearchForm } }

Step 2:定义配置项和搜索参数

export default { data() { return { // 搜索参数,字段名需与 config 中的 prop 对应 queryParams: { username: '', status: '', dateRange: [] }, // 搜索配置 searchConfig: [ { label: '用户名', prop: 'username', type: 'input' }, { label: '状态', prop: 'status', type: 'select', options: [ { label: '启用', value: 1 }, { label: '禁用', value: 0 } ] }, { label: '创建时间', prop: 'dateRange', type: 'date', dateType: 'daterange', valueFormat: 'yyyy-MM-dd' } ] } } }

Step 3:在模板中使用

<template> <div class="page-container"> <SearchForm :config="searchConfig" :model.sync="queryParams" @search="handleSearch" > <!-- 通过插槽添加额外按钮 --> <el-button type="success" icon="el-icon-download">导出</el-button> </SearchForm> <!-- 表格 --> <el-table :data="tableData"> <!-- ... --> </el-table> </div> </template> <script> export default { methods: { handleSearch() { console.log('开始搜索,参数为:', this.queryParams) // 调用 API 获取列表数据 // this.getList() } } } </script>

四、进阶技巧:动态显隐与联动 🔗

1. 动态显示/隐藏表单项

利用v-if的特性,我们可以通过计算属性来控制config

computed: { dynamicConfig() { const config = [...this.searchConfig] // 如果不是管理员,隐藏“所属部门”搜索项 if (!this.isAdmin) { return config.filter(item => item.prop !== 'deptId') } return config } }

2. 表单联动(例如:选择了A,B才可选)

// 在 config 中添加 disabled 逻辑 { label: '子选项', prop: 'child', type: 'select', disabled: () => !this.queryParams.parentId // 利用函数返回 }

五、总结 📝

通过封装SearchForm组件,我们将原本几十行的模板代码缩减到了几行配置。

封装的好处显而易见:

  • 开发效率翻倍:新页面只需配置config

  • 风格高度统一:再也不会出现 A 页面搜索框宽 200px,B 页面宽 220px 的情况。

  • 维护成本低:修改搜索逻辑只需改一处。

这种配置化的思想,是中级向高级前端进阶的必经之路。

http://www.jsqmd.com/news/652351/

相关文章:

  • XCharts 深度解析:Unity 数据可视化图表插件实战指南
  • 力扣热门100题之跳跃游戏
  • 超越Grad-CAM:用大核卷积论文技巧可视化你的CNN感受野(含Colab链接)
  • 面试官视角:操作系统八股文背后的设计哲学与工程权衡(附高频考点拆解)
  • 监管沙盒已批!2026奇点大会公布的AI理财顾问持牌路径全解析,附银保监2025-11号文实操对照表
  • 别再傻傻分不清了!从光线投射到路径追踪,一张图看懂光线追踪的进化史
  • 04-07-06 界定问题框架 - 学习笔记
  • Python实战:打造高效GUI工具,实现BLF与ASC格式CAN数据的批量互转
  • 格式革命:Paperxie 智能排版,让毕业论文告别 “格式地狱“,10 分钟解锁毕业通关密码
  • Dagum基尼系数分解工具:无代码化操作与多场景应用指南
  • Windows Server 2012上IIS配置全攻略:从开启功能到发布第一个网页(附防火墙设置)
  • Redis 主从同步步骤总结
  • 一文读懂:状态管理在Agent中的关键作用与实现
  • 告别DLL缺失烦恼:Visual C++运行库终极一站式解决方案
  • AMD Ryzen调试工具SMUDebugTool完整使用指南:从零开始掌握专业级硬件调优
  • 告别自签名警告!用mkcert 1.4.1为本地开发环境一键搞定HTTPS证书(Windows/Linux保姆级教程)
  • 终极指南:如何用Nucleus Co-Op实现单机游戏本地分屏多人联机
  • 三步永久保存微信聊天记录:WeChatMsg让你告别数据丢失的烦恼
  • DriverStore Explorer完全手册:3步彻底解决Windows驱动管理难题
  • 头部应用鸿蒙重构深度案例:微信、支付宝的适配路径与体验跃迁
  • 为什么你家的Wi-Fi总卡顿?从CSMA/CA协议聊聊无线网络的‘先礼后兵’机制
  • VCU整车Simulink应用层模型:涵盖高压上下电、车辆蠕动等多元功能,全局仿真通过,适用于...
  • 论文格式零门槛通关:Paperxie 用 4000 + 高校模板,终结你的排版内耗
  • 磁编码器选型实战:从AS5047到MA730,如何为你的电机控制项目挑选最佳方案?
  • 终极指南:如何在Windows 11上免费实现经典游戏局域网联机?
  • SPSC2环形队列
  • 【观察】HPE Smart Choice赋能伙伴:交付快一步,赢单稳一筹
  • 【国家级AI安全审计框架】:融合NIST AI RMF与中国《生成式AI服务管理暂行办法》的12项强制检查项
  • Agent 记忆系统设计:短期、长期到知识图谱
  • 不止于点亮:在Efinix SapphireSoc软核上实现程序固化与独立启动的完整攻略