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

一个极简单的 VUE3 + Element-Plus 查询表单展开收起功能组件

在管理系统页面开发时,会遇到一个简单又令人头痛的问题,那就是:搜索页面太多,搜索表单项内容太多。对于过多的内容,往往采取折叠的形式,仅展示部分内容,需要时展开查看全部。

如果在程序设计时不注意,就会在项目中出现大量、重复的展开折叠逻辑,使得代码冗余不说,后期一旦有逻辑改动,维护起来也相当繁琐。

为此需要设计一个组件来实现表单展开折叠的功能,具体需求如下:

  1. 默认展示表单项和更多表单项由开发者自定;
  2. 当没有更多表单项时,不出现展开/折叠按钮,且不需要每个表单传参控制;
  3. 当表单项成一行展示时,操作按钮在最右边;当表单项成多行展示时,表单按钮在右下方;
  4. 能够控制表单项之间的距离;
  5. 按下回车按钮时,触发搜索。

具体实现

对于默认展示表单项,以及更多的表单项,使用插槽来控制。默认展示的表单项,直接使用默认插槽;更多的表单项,包裹在一个具名插槽extra中。如此,在控制更多的表单项时,只需控制具名插槽的显示/隐藏就可以了。

<slot></slot>
<template v-if="isMore"><slot name="extra"></slot>
</template><script setup>
import { ref } from 'vue'const isMore = ref(false)
</script>

通过判断是否有具名插槽extra ,就可以知道是否有更多表单项。从而实现控制在没有更多表单项时不出现展开/折叠按钮。

<script setup>
import { useSlots } from 'vue'
// 是否有更多表单项
const hasExtraSlot = useSlots().extra
<script/>

为了使操作按钮始终在表单的右下方,这里使用浮动布局来实现。

<div class="search-form-wrapper"><slot></slot><template v-if="isMore"><slot name="extra"></slot></template><!--操作按钮容器--><div class="search-form-wrapper__op"></div>
</div><style lang="less">
.search-form-wrapper {&__op {float: right;}
}
</style>

表单项之间的距离控制。通过外部传入距离数据,组件内部控制样式实现。为了减少不必要的遍历表单和复杂逻辑,采用css样式变量来控制。

<template><divclass="search-form-wrapper":style="{ '--form-item-padding': gutter / 2 + 'px', margin: `0 -${gutter / 2}px -18px` }"></div>
<template><script setup>
defineProps({// 表单项之间的距离gutter: {type: Number,default: 20}
})
</script><style lang="less">
.search-form-wrapper {&__op {float: right;padding: 0 var(--form-item-padding);}.el-form-item {padding: 0 var(--form-item-padding);margin-right: 0;}
}
</style>

在按下回车键时触发搜索,一个方法是为每个表单项添加enter键盘事件,但是这种方法比较繁琐。另一个比较简单的方法是,为<form>标签绑定enter键盘事件。

<script setup>
import { onMounted, onUnmounted } from 'vue'function handleEvent(e) {if (e.keyCode === 13) {search() // 搜索e.preventDefault()}
}// el-form 不在本组件内封装,作为本组件的父组件
// 监听父级表单的keydown事件,当按下回车键时触发查询操作
onMounted(() => {const wrapper = document.querySelector('.search-form-wrapper')try {if (Array.from(wrapper.parentNode.classList).includes('el-form')) {wrapper.parentNode.addEventListener('keydown', handleEvent)onUnmounted(() => {wrapper.parentNode.removeEventListener('keydown', handleEvent)})}} catch (e) {console.error(e)}
})
</script>

完整代码

<!-- SearchFormWrapper.vue -->
<template><divclass="search-form-wrapper":style="{ '--form-item-padding': gutter / 2 + 'px', margin: `0 -${gutter / 2}px -18px` }"><slot></slot><template v-if="isMore"><slot name="extra"></slot></template><div class="search-form-wrapper__op"><el-button type="success" @click="search">查询</el-button><el-button @click="reset">重置</el-button><el-linkv-if="hasExtraSlot"class="ml10"type="primary":underline="false"@click="toggleMore">{{ moreText }}<el-icon style="margin-left: 5px"><ArrowUp v-if="isMore" /><ArrowDown v-else /></el-icon></el-link></div></div>
</template><script setup>
import { onMounted, onUnmounted, ref, useSlots } from 'vue'defineProps({gutter: {type: Number,default: 20}
})const isMore = ref(false)
const moreText = ref('更多筛选')const toggleMore = () => {isMore.value = !isMore.valuemoreText.value = isMore.value ? '收起筛选' : '更多筛选'
}const hasExtraSlot = useSlots().extraconst emit = defineEmits(['search', 'reset'])function search() {emit('search')
}function reset() {emit('reset')
}function handleEvent(e) {if (e.keyCode === 13) {search()e.preventDefault()}
}// 监听父级表单的keydown事件,当按下回车键时触发查询操作
onMounted(() => {const wrapper = document.querySelector('.search-form-wrapper')try {if (Array.from(wrapper.parentNode.classList).includes('el-form')) {wrapper.parentNode.addEventListener('keydown', handleEvent)onUnmounted(() => {wrapper.parentNode.removeEventListener('keydown', handleEvent)})}} catch (e) {console.error(e)}
})
</script><style lang="less">
.search-form-wrapper {&__op {float: right;padding: 0 var(--form-item-padding);}.el-form-item {padding: 0 var(--form-item-padding);margin-right: 0; // 表单inline模式会有margin-rihgt影响,需要重置它}
}
</style>

使用示例

其中用到的样式类 w_25 是一个原子类,表示 width: 25%

<template><el-form :model="searchForm" :inline="true"><SearchFormWrapper @search="handleSearch" @reset="handleReset"><el-form-item class="w_25" label="表单项1"><el-input v-model="test1"/></el-form-item><el-form-item class="w_25" label="表单项2"><el-input v-model="test2"/></el-form-item><template slot="extra"><el-form-item class="w_25" label="表单项3"><el-input v-model="test2"/></el-form-item><el-form-item class="w_25" label="表单项4"><el-input v-model="test2"/></el-form-item></template></SearchFormWrapper></el-form>
</template><script setup>
import { ref } from 'vue'const searchForm = ref({test1: '',test2: '',test3: '',test4: ''
})// 搜索
function handleSearch() {}// 重置
function handleReset() {}
</script>

相关文章:

一个极简单的 VUE3 + Element-Plus 查询表单展开收起功能组件

在管理系统页面开发时&#xff0c;会遇到一个简单又令人头痛的问题&#xff0c;那就是&#xff1a;搜索页面太多&#xff0c;搜索表单项内容太多。对于过多的内容&#xff0c;往往采取折叠的形式&#xff0c;仅展示部分内容&#xff0c;需要时展开查看全部。 如果在程序设计时…...

es 里的Filesystem Cache 理解

文章目录 背景问题1&#xff0c;Filesystem Cache 里放的是啥问题2&#xff0c;哪些查询它们会受益于文件系统缓存问题3 查询分析 背景 对于es 优化来说常常看到会有一条结论给&#xff0c;给 JVM Heap 最多不超过物理内存的 50%&#xff0c;且不要超过 31GB&#xff08;避免压…...

Linux进程10-有名管道概述、创建、读写操作、两个管道进程间通信、读写规律(只读、只写、读写区别)、设置阻塞/非阻塞

目录 1.有名管道 1.1概述 1.2与无名管道的差异 2.有名管道的创建 2.1 直接用shell命令创建有名管道 2.2使用mkfifo函数创建有名管道 3.有名管道读写操作 3.1单次读写 3.2多次读写 4.有名管道进程间通信 4.1回合制通信 4.2父子进程通信 5.有名管道读写规律&#xff…...

精品可编辑PPT | 全面风险管理信息系统项目建设风控一体化标准方案

这份文档是一份全面风险管理信息系统项目建设风控一体化标准方案&#xff0c;涵盖了业务架构、功能方案、系统技术架构设计、项目实施及服务等多个方面的详细内容。方案旨在通过信息化手段提升企业全面风险管理工作水平&#xff0c;促进风险管理落地和内部控制规范化&#xff0…...

YOLOv8网络结构

YOLOv8的网络结构由输入端(Input)、骨干网络(Backbone)、颈部网络(Neck)和检测头(Head)四部分组成。 YOLOv8的网络结构如下图所示&#xff1a; 在整个系统架构中&#xff0c;图像首先进入输入处理模块&#xff0c;该模块承担着图像预处理与数据增强的双重任务。接着&#xff0c…...

数组对象 按照对象中的某个字段排序

在JavaScript中&#xff0c;可以使用数组的sort()方法按照对象中的某个字段对数组进行排序。 按照对象中的某个字段对数组进行排序&#xff1a; 基本排序方法 升序排序 const array [{ name: John, age: 25 },{ name: Jane, age: 21 },{ name: Bob, age: 30 } ];// 按照age字…...

笔记本电脑升级实战手册【扩展篇1】:flash id查询硬盘颗粒

文章目录 前言&#xff1a;一、硬盘颗粒介绍1、MLC&#xff08;Multi-Level Cell&#xff09;2、TLC&#xff08;Triple-Level Cell&#xff09;3、QLC&#xff08;Quad-Level Cell&#xff09; 二、硬盘与主控1、主控介绍2、主流主控厂家 三 、硬盘颗粒查询使用flash id工具查…...

AutoDL租用服务器教程

在跑ai模型的时候&#xff0c;容易遇到算力不够的情况。此时便需要租用服务器。autodl是个较为便宜的服务器租用平台&#xff0c;h20仅需七点几元每小时。下面是简单的介绍。 打开网站AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDL&#xff0c;并登录账号 登录后&#xff…...

四、STM32 HAL库API完全指南:从功能分类到实战示例

STM32 HAL库API完全指南&#xff1a;从功能分类到实战示例 一、HAL库API的总体架构 STM32 HAL库&#xff08;Hardware Abstraction Layer&#xff09;作为STMicroelectronics推出的统一驱动框架&#xff0c;提供了覆盖所有STM32外设的标准化API。HAL库的API设计遵循严格的分层…...

MySQL全量、增量备份与恢复

目录 数据备份 一、数据备份类型 二、常见备份方法 扩展&#xff1a;GTID与XtraBackup ‌一、GTID&#xff08;全局事务标识符&#xff09;‌ ‌1. 定义与核心作用‌ ‌2. GTID在备份恢复中的意义‌ ‌3. GTID配置与启用‌ ‌二、XtraBackup的意义与核心价值‌ ‌1. 定…...

fastboot 如何只刷system.img 分区

在 fastboot 模式下只刷入 system.img 分区&#xff0c;可以按照以下步骤操作&#xff1a; 1. 确保设备已进入 Fastboot 模式 连接设备到电脑&#xff0c;并确保已进入 Fastboot/Bootloader 模式&#xff1a;adb reboot bootloader或手动进入&#xff08;通常为 电源键 音量…...

连接词化归律详解

1. 连接词化归律的基本概念 连接词化归律(也称为归结原理)是数理逻辑中用于简化逻辑表达式的重要方法&#xff0c;它允许我们将复杂的逻辑表达式转化为更简单的等价形式&#xff0c;特别是转化为合取范式(CNF)或析取范式(DNF)。 核心思想 连接词化归律基于一系列逻辑等价关系…...

《构建社交应用用户激励引擎:React Native与Flutter实战解析》

React Native凭借其与JavaScript和React的紧密联系&#xff0c;为开发者提供了一个熟悉且灵活的开发环境。在构建用户等级体系时&#xff0c;它能够充分利用现有的前端开发知识和工具。通过将用户在社交应用中的各种行为进行量化&#xff0c;比如发布动态的数量、点赞评论的次数…...

goner/otel 在Gone框架接入OpenTelemetry

文章目录 背景与意义快速上手&#xff1a;五步集成 OpenTelemetry运行效果展示代码详解与实践目录结构说明组件加载&#xff08;module.load.go&#xff09;业务组件示例&#xff08;your_component.go&#xff09;程序入口&#xff08;main.go&#xff09; 进阶用法与最佳实践…...

杨校老师项目之基于SSM与JSP的鲜花销售系统-【成品设计含文档】

基于SSMJSP鲜花商城系统 随着电子商务的快速发展&#xff0c;鲜花在线销售已成为一种重要的消费模式。本文设计并实现了一个基于JSP技术的鲜花销售管理系统&#xff0c;采用B/S架构&#xff0c;使用SSM框架进行开发&#xff0c;并结合Maven进行项目依赖管理。系统分为前台用户模…...

springboot集成langchain4j实现票务助手实战

前言 看此篇的前置知识为langchain4j整合springboot&#xff0c;以及springboot集成langchain4j记忆对话。 Function-Calls介绍 langchain4j 中的 Function Calls&#xff08;函数调用&#xff09;是一种让大语言模型&#xff08;LLM&#xff09;与外部工具&#xff08;如 A…...

Feed流推送之订阅推送

分类 feed流分为TimeLine和智能排序&#xff0c;前者不对内容进行过滤&#xff0c;一般根据发布的时间来进行排序&#xff0c;一般用于好友动态或者推送关注的人的消息&#xff0c;而后者一般有着复杂的算法&#xff0c;可以根据算法智能地向目标用户推送内容&#xff0c;例如…...

wordpress自学笔记 第四节 商城菜单的添加和修改美化

wordpress自学笔记 摘自 超详细WordPress搭建独立站商城教程-第四节 商城菜单的添加和修改美化&#xff0c;2025 WordPress搭建独立站商城#WordPress建站教程https://www.bilibili.com/video/BV1UwwgeuEkK?spm_id_from333.788.videopod.sections&vd_sourcea0af3bbc6b6d…...

GPU L2 Cache一致性协议对科学计算的影响研究

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 一、GPU缓存层级革命&#xff1a;从Volta到Hopper的演进图谱 1.1 架构级缓存策略对比 ‌Vo…...

C++中类中const知识应用详解

下面将从**const 成员**、const 成员函数、const 对象、mutable、constexpr 等方面&#xff0c;逐一详解 C 类中常见的 const 用法及注意事项&#xff0c;并配合示例。 一、const 数据成员 必须在初始化列表中初始化 class A {const int x; // const 成员 public:A(int v) :…...

【速写】KV-cache与解码的再探讨(以束搜索实现为例)

文章目录 1 Beam Search 解码算法实现2 实现带KV Cache的Beam Search解码3 关于在带kv-cache的情况下的use_cache参数 1 Beam Search 解码算法实现 下面是一个使用PyTorch实现的beam search解码算法&#xff1a; 几个小细节&#xff1a; 束搜索可以加入length_penalty&#…...

(网络)应用层协议-HTTPS

1.HTTPS是什么&#xff1f; HTTPS是应用层的一种协议&#xff0c;是在HTTP的基础上进行了加密层的处理。 HTTP协议的内容都是按照文本的形式进行传输的&#xff0c;所以呢就很容易被别人知道传输的是什么。 我们在了解了TCP/IP之后是知道我们的数据在传输的过程中是通过路由器进…...

vue3: pdf.js 3.4.120 using javascript

npm install pdfjs-dist3.4.120 项目结构&#xff1a; pdfjsViewer.vue <template><div><div v-if"loading" class"flex justify-center items-center py-8"><div class"animate-spin rounded-full h-12 w-12 border-b-2 borde…...

Spark目前支持的部署模式。

一、本地模式&#xff08;Local Mode&#xff09; 特点&#xff1a; 在单台机器上运行&#xff0c;无需集群。主要用于开发、测试和调试。所有组件&#xff08;Driver、Executor&#xff09;在同一个 JVM 中运行。 启动命令&#xff1a; bash spark-submit --master local[*]…...

想实现一个基于MCP的pptx生成系统架构图【初版实现】

技术栈:Python + MCP协议 + python-pptx + FastMCP 核心创新点:通过MCP协议实现PPTX元素的动态化生成与标准化模板管理 当前还是个半成品,后续持续更新。 主要先介绍一下思路。 一、MCP协议与系统设计原理 1.1 为什么选择MCP? 标准化工具调用:通过MCP将PPTX元素生成逻辑封…...

PyTorch Lightning实战 - 训练 MNIST 数据集

MNIST with PyTorch Lightning 利用 PyTorch Lightning 训练 MNIST 数据。验证梯度范数、学习率、优化器对训练的影响。 pip show lightning Version: 2.5.1.post0Fast dev run DATASET_DIR"/repos/datasets" python mnist_pl.py --output_grad_norm --fast_dev_run…...

力扣2094题解

记录&#xff1a; 2025.5.12 题目&#xff1a; 思路&#xff1a; 暴力遍历。 解题步骤&#xff1a; 1.统计数字出现次数&#xff1a;使用数组cnt来记录输入数组中每个数字的出现次数。 2.生成三位偶数&#xff1a;通过循环从100开始&#xff0c;每次递增2&#xff0c;生成…...

DHCP自动分配IP

DHCP自动分配IP 练习1 路由器 Router>en Router#conf t Router(config)#ip dhcp pool ip10 //创建DHCP地址池 Router(dhcp-config)#network 192.168.20.0 255.255.255.0 // 配置网络地址和子网掩码 Router(dhcp-config)#default-router 192.168.20.254 //配置默认网关 Rou…...

【CF】Day57——Codeforces Round 955 (Div. 2, with prizes from NEAR!) BCD

B. Collatz Conjecture 题目&#xff1a; 思路&#xff1a; 简单模拟 很简单的模拟&#xff0c;我们只需要快速的找到下一个离 x 最近的 y 的倍数即可&#xff08;要大于 x&#xff09; 这里我们可以这样写 add y - (x % y)&#xff0c;这样就知道如果 x 要变成 y 的倍数还要…...

(done) 补充:xv6 的一个用户程序 init 是怎么启动的 ?它如何启动第一个 bash ?

先看 main.c 从函数名来看&#xff0c;比较相关的就 userinit() 和 scheduler() #include "types.h" #include "param.h" #include "memlayout.h" #include "riscv.h" #include "defs.h"volatile static int started 0;//…...