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

Vue2中利用$attrs和$listeners实现el-input的高效二次封装

1. 为什么需要二次封装el-input组件在实际的Vue2项目开发中我们经常会遇到需要对Element UI的el-input组件进行二次封装的情况。这通常出于以下几个原因首先项目往往有统一的设计规范。比如所有输入框都需要有特定的边框样式、圆角大小或者hover效果。如果每个页面都单独写样式不仅效率低下而且难以维护。我在最近的一个后台管理系统项目中就遇到这种情况设计师要求所有输入框都要有浅蓝色的边框和圆角效果。其次业务逻辑的复用需求。比如手机号输入框需要自动格式化、密码输入框需要统一的强度校验规则。把这些逻辑封装起来可以避免重复代码我在电商项目中就封装过一个带自动格式化的手机号输入组件。最后与后端API的对接需求。比如某些字段需要特定的校验规则或者需要处理特殊的数据格式。通过封装可以统一这些处理逻辑。2. 理解$attrs和$listeners的核心作用在Vue2中$attrs和$listeners是实现组件属性透传的关键属性。让我用一个生活中的例子来解释想象你是一个快递员子组件$attrs就像是你收到的包裹上所有的标签信息收件人、电话、地址等而$listeners则是寄件人父组件给你的所有指示比如要本人签收、放在快递柜等。具体来说$attrs包含父组件传递的所有非prop属性除了class和style$listeners包含父组件传递的所有事件监听器在el-input的封装场景中这两个属性特别有用。比如父组件传递了placeholder、disabled等属性或者绑定了focus、blur等事件我们都可以通过它们自动传递给内部的el-input。3. 基础封装实现步骤3.1 创建基础封装组件我们先创建一个最基本的封装组件MyInput.vuetemplate div classmy-input-wrapper el-input v-bind$attrs v-on$listeners :valuevalue inputhandleInput /el-input /div /template script export default { name: MyInput, inheritAttrs: false, props: { value: [String, Number] }, methods: { handleInput(val) { this.$emit(input, val) } } } /script style scoped .my-input-wrapper { margin-bottom: 15px; } /style这里有几个关键点inheritAttrs: false阻止自动绑定属性到根元素v-bind$attrs将所有属性传递给el-inputv-on$listeners将所有事件监听器传递给el-input显式处理v-model需要的value和input3.2 处理特殊属性和事件有时候我们需要对某些属性或事件进行特殊处理。比如要给所有输入框添加统一的校验逻辑computed: { filteredListeners() { const listeners {...this.$listeners} // 添加统一的blur校验 listeners.blur (e) { this.validate() if (this.$listeners.blur) { this.$listeners.blur(e) } } return listeners } }, methods: { validate() { // 统一的校验逻辑 } }4. 高级封装技巧4.1 添加自定义样式我们可以通过插槽和样式穿透来增强el-input的样式template el-input v-bind$attrs v-onfilteredListeners :class[custom-input, $attrs.class] :style$attrs.style template v-for(slot, name) in $slots #[name] slot :namename/slot /template /el-input /template style scoped .custom-input { border-radius: 8px; } /deep/ .el-input__inner { background-color: #f5f7fa; } /style4.2 处理v-model的特殊情况对于v-model的处理有时候需要额外的逻辑props: { value: [String, Number], trim: { type: Boolean, default: false } }, methods: { handleInput(val) { let output val if (this.trim) { output output.trim() } this.$emit(input, output) } }5. 实际应用中的常见问题5.1 属性冲突问题当封装组件和el-input有同名prop时需要注意处理优先级。比如size属性props: { size: { type: String, default: medium } }, computed: { mergedProps() { return { size: this.size, ...this.$attrs } } }5.2 事件覆盖问题如果要在封装组件中添加新事件同时保留原有事件methods: { handleFocus(e) { console.log(自定义focus处理) this.$emit(focus, e) if (this.$listeners.focus) { this.$listeners.focus(e) } } }6. 完整示例代码下面是一个功能完整的el-input封装组件示例template div classenhanced-input label v-iflabel classinput-label{{ label }}/label el-input refinput v-bindmergedAttrs v-onmergedListeners :valueinnerValue inputhandleInput blurhandleBlur template v-for(slot, name) in $slots #[name] slot :namename/slot /template /el-input div v-iferrorMessage classerror-message{{ errorMessage }}/div /div /template script export default { name: EnhancedInput, inheritAttrs: false, props: { value: [String, Number], label: String, rules: Array, trim: { type: Boolean, default: false } }, data() { return { innerValue: this.value, errorMessage: } }, computed: { mergedAttrs() { return { size: medium, ...this.$attrs, class: [custom-input, this.$attrs.class] } }, mergedListeners() { const listeners {...this.$listeners} // 移除我们手动处理的事件 delete listeners.input delete listeners.blur return listeners } }, watch: { value(newVal) { this.innerValue newVal } }, methods: { handleInput(val) { let output val if (this.trim) { output output.trim() } this.innerValue output this.$emit(input, output) }, handleBlur(e) { this.validate() this.$emit(blur, e) }, validate() { if (!this.rules) return true // 实现校验逻辑 const errors this.rules.map(rule { if (rule.required !this.innerValue) { return rule.message || 该字段为必填项 } // 其他校验规则... return null }).filter(Boolean) this.errorMessage errors[0] || return !this.errorMessage }, focus() { this.$refs.input.focus() } } } /script style scoped .enhanced-input { margin-bottom: 20px; } .input-label { display: block; margin-bottom: 8px; font-weight: 500; } .error-message { color: #f56c6c; font-size: 12px; margin-top: 4px; } .custom-input /deep/ .el-input__inner { border-radius: 4px; transition: all 0.3s; } .custom-input /deep/ .el-input__inner:hover { border-color: #409eff; } /style7. 性能优化建议在大量使用封装组件时可以考虑以下优化避免在computed中进行复杂计算对于静态样式尽量使用scoped样式而不是动态绑定使用debounce处理频繁触发的事件合理使用v-once处理不会变化的部分// 使用lodash的debounce import { debounce } from lodash methods: { handleInput: debounce(function(val) { this.$emit(input, val) }, 300) }8. 测试与调试技巧在开发封装组件时完善的测试很重要测试属性透传是否正常my-input placeholder请输入 disabled/my-input测试事件绑定是否正常my-input focushandleFocus blurhandleBlur/my-input测试v-model双向绑定my-input v-modelusername/my-input测试插槽内容my-input template #prefix i classel-icon-search/i /template /my-input在组件内部可以添加调试代码mounted() { console.log(接收到的attrs:, this.$attrs) console.log(接收到的listeners:, this.$listeners) }

相关文章:

Vue2中利用$attrs和$listeners实现el-input的高效二次封装

1. 为什么需要二次封装el-input组件 在实际的Vue2项目开发中,我们经常会遇到需要对Element UI的el-input组件进行二次封装的情况。这通常出于以下几个原因: 首先,项目往往有统一的设计规范。比如所有输入框都需要有特定的边框样式、圆角大小或…...

Boost库编译避坑指南:从下载到测试的完整流程(VS2013实战)

Boost库编译避坑指南:从下载到测试的完整流程(VS2013实战) Boost库作为C开发者必备的工具集,其强大的功能与跨平台特性使其在项目开发中占据重要地位。然而,对于初次接触Boost的开发者而言,编译过程往往充…...

避坑指南:为什么MATLAB的geotiffread无法识别你手动修改的TIF文件?从底层解析TIFF格式差异

深度解析:MATLAB处理手动修改TIF文件失败的底层机制与解决方案 1. TIFF与GeoTIFF格式的本质差异 许多开发者在使用MATLAB处理遥感或地理空间数据时,常常会遇到一个令人困惑的问题:为什么通过专业GIS软件(如ENVI、ArcMap&#xff0…...

Simulink模型连线太乱?试试这3个隐藏功能,一键自动整理清爽又高效

Simulink模型整洁度提升实战:3个被低估的高效功能详解 当你打开一个布满蜘蛛网般连线的Simulink模型时,是否曾感到一阵眩晕?那些交错缠绕的信号线、随意堆放的模块和难以追踪的数据流向,不仅影响视觉体验,更会显著降低…...

AUKF算法在DSP28335上的实现与CCS6编译之旅

AUKF/自适应无迹卡尔曼滤波算法C代码,CCS6软件编译,微控为DSP28335,可下载运行。最近在研究滤波算法,其中自适应无迹卡尔曼滤波(AUKF)算法特别吸引我,于是决定在DSP28335微控上用C代码实现它&am…...

Harmonyos应用实例162:二次函数图象变换实验室

应用实例二:二次函数图象变换实验室 知识点:第二十二章《二次函数》—— 图象与性质。 功能:通过滑块控制参数 a,h,ka, h, ka,h,k,实时绘制 y=a(x−h)2+ky=a(x-h)^2+k...

Harmonyos应用实例161:一元二次方程求根公式推导器

应用实例一:一元二次方程求根公式推导器 知识点:第二十一章《一元二次方程》—— 配方法与公式法。 功能:学生输入方程 ax2+bx+c=0ax^2+bx+c=0ax2<...

Harmonyos应用实例160:数据分析与决策

应用实例十:数据分析与决策 知识点:第二十章《数据的分析》—— 用样本估计总体。 功能:模拟“鱼塘捕鱼”问题。学生先捕捞一部分鱼做标记放回,再随机捕捞抽样,输入抽样中有标记的鱼的数量,应用估算鱼塘总数,体验样本估计总体的统计思想。 @Entry @Component struct …...

安卓逆向实战:用Node.js一键清理混淆dex中的Unicode垃圾代码(附完整工具链)

安卓逆向工程中的Unicode混淆清理实战&#xff1a;基于Node.js的高效自动化方案 在移动安全研究领域&#xff0c;安卓应用的逆向分析是获取关键信息的重要手段。然而&#xff0c;开发者常采用各种混淆技术增加分析难度&#xff0c;其中Unicode组合符号和无效方法调用是最常见的…...

我的世界皮肤格式转换神器SkinConvertingSheep使用指南(附下载链接)

我的世界皮肤格式转换神器SkinConvertingSheep使用指南 在《我的世界》的丰富自定义生态中&#xff0c;皮肤作为玩家个性化表达的重要载体&#xff0c;其格式兼容性问题常常困扰着创作者和普通玩家。当你在PCL2启动器中尝试应用心仪的皮肤时&#xff0c;突然弹出的"请使用…...

AMD FSR 1.0源码实战:手把手教你实现边缘自适应升频(附完整代码解析)

AMD FSR 1.0源码实战&#xff1a;手把手教你实现边缘自适应升频&#xff08;附完整代码解析&#xff09; 在游戏开发领域&#xff0c;实时渲染的性能与画质始终是一对难以调和的矛盾。AMD开源的FidelityFX Super Resolution&#xff08;FSR&#xff09;技术为解决这一矛盾提供了…...

GWAS新手必看:从PLINK到GEMMA的完整分析流程(附代码)

GWAS实战指南&#xff1a;从数据质控到结果解读的全流程解析 对于刚接触全基因组关联分析&#xff08;GWAS&#xff09;的生物信息学研究者来说&#xff0c;如何从海量的基因型数据中挖掘出有意义的遗传关联是个不小的挑战。本文将带你系统掌握GWAS分析的核心流程&#xff0c;重…...

从单机到分布式:MySQL与GaussDB架构差异详解(附性能测试数据)

从单机到分布式&#xff1a;MySQL与GaussDB架构差异详解&#xff08;附性能测试数据&#xff09; 在数据库技术快速迭代的今天&#xff0c;架构设计的选择往往决定了系统未来的扩展边界。当业务从初创期的小流量发展到百万级并发时&#xff0c;单机数据库的瓶颈会突然暴露——连…...

手机也能做PCB设计?这款Droid PCB APP让你随时随地搞定电路板布局

手机也能做PCB设计&#xff1f;Droid PCB APP重新定义移动办公的电子工程师效率 作为一名经常需要现场调试电路的电子工程师&#xff0c;我曾在高铁站、咖啡厅甚至机场候机室里无数次打开笔记本电脑&#xff0c;只为修改一个简单的PCB走线。直到发现Droid PCB这款移动端设计工具…...

嵌入式内存管理“潜规则”:从.data/.bss段搬运,看ld脚本如何影响启动速度和功耗

嵌入式内存管理的性能优化艺术&#xff1a;从.data/.bss段搬运到ld脚本的实战精要 在资源受限的嵌入式系统中&#xff0c;每一个字节的内存和每一微秒的启动时间都弥足珍贵。当我们谈论物联网设备或电池供电产品的开发时&#xff0c;内存管理不再是简单的变量声明与使用&#x…...

【银河麒麟高级服务器操作系统】安全配置基线实战:从问题定位到参数调优的深度解析

1. 问题定位&#xff1a;当安全基线配置突然失效时 第一次在银河麒麟V10 SP1系统上执行安全加固时&#xff0c;我盯着终端反复确认了三次——明明按照标准文档配置了groupwheel参数&#xff0c;为什么普通用户还是能随意切换到root&#xff1f;这个发现让我后背发凉&#xff0c…...

Win10蓝屏CRITICAL_PROCESS_DIED:从错误诊断到系统修复全流程解析

1. 当Win10突然蓝屏&#xff1a;CRITICAL_PROCESS_DIED意味着什么&#xff1f; 电脑用得好好的&#xff0c;突然屏幕一蓝&#xff0c;跳出一行"CRITICAL_PROCESS_DIED"的白字——这大概是每个Windows用户最不想看到的画面之一。这个错误直译为"关键进程死亡&quo…...

Windows11+WSL2+Ubuntu22.04环境下,5分钟搞定Qemu虚拟VExpress-A9开发板环境配置

Windows 11 WSL2 Ubuntu 22.04 极速搭建 QEMU 虚拟开发环境指南 对于嵌入式开发者而言&#xff0c;拥有一套随时可用的开发环境至关重要。本文将带你快速在 Windows 11 系统上&#xff0c;通过 WSL2 和 Ubuntu 22.04 搭建完整的 QEMU 虚拟开发环境&#xff0c;无需实体开发板…...

FT8430-LRT非隔离5V100MA电源芯片:小家电、智能照明与MCU供电的高效解决方案(附典型电路图)

1. FT8430-LRT芯片&#xff1a;小功率设备的"能量心脏" 当你拆开一个智能灯泡或者电动牙刷&#xff0c;总会发现一块小小的电路板&#xff0c;上面密密麻麻的元件中藏着一个不起眼但至关重要的部件——电源管理芯片。FT8430-LRT就是这样一款专为小功率设备设计的非隔…...

【Redis】Redis常用命令速查表(完整版)

文章目录Redis常用命令速查表一、基础核心类型常用命令二、其他类型常用命令Redis 常用命令-具体命令行使用示例一、基础核心类型常用命令示例二、其他类型常用命令示例Redis常用命令速查表 一、基础核心类型常用命令 数据类型命令核心作用StringSET设置key-value对&#xff0…...

OpenMVS在文化遗产保护中的应用:如何用多视图立体视觉重建敦煌壁画

OpenMVS在文化遗产保护中的应用&#xff1a;如何用多视图立体视觉重建敦煌壁画 敦煌莫高窟的壁画艺术是人类文明的瑰宝&#xff0c;但时间的流逝和自然环境的侵蚀让这些珍贵文物面临不可逆的损伤。如何用数字技术将这些文化遗产永久保存下来&#xff1f;OpenMVS作为工业级多视图…...

FileZilla FTP服务器搭建全攻略:从安装到被动模式配置(附防火墙设置)

FileZilla FTP服务器搭建全攻略&#xff1a;从安装到被动模式配置&#xff08;附防火墙设置&#xff09; 在企业内部文件共享或远程协作场景中&#xff0c;FTP&#xff08;文件传输协议&#xff09;仍然是跨平台文件传输的可靠选择。作为开源FTP解决方案的标杆&#xff0c;File…...

从HTTP到HTTPS:用OpenSSL自制证书实现gRPC双向认证(2024最新版)

2024实战指南&#xff1a;基于OpenSSL构建gRPC双向认证体系 在微服务架构盛行的今天&#xff0c;gRPC凭借其高性能、跨语言特性成为服务间通信的首选方案。但当涉及敏感数据传输时&#xff0c;仅依赖HTTP/2的默认加密远远不够——我们需要建立完整的证书信任链。本文将带您从零…...

Western blot (WB) 灰度分析进阶指南:ImageJ 自动化批处理技巧

1. 为什么需要自动化WB灰度分析&#xff1f; 做过Western blot的人都知道&#xff0c;手动分析十几张甚至几十张膜图像有多痛苦。每次都要重复"画框-测量-记录"的机械操作&#xff0c;不仅效率低下&#xff0c;还容易因为手抖选错区域。我实验室曾经有个博士生&#…...

SecureCRT密钥登录Linux服务器保姆级教程(含SFTP下载私钥全流程)

SecureCRT密钥登录Linux服务器全流程实战指南 对于需要频繁登录Linux服务器的运维人员和开发者来说&#xff0c;每次输入密码既低效又存在安全隐患。SecureCRT作为一款专业终端工具&#xff0c;配合SSH密钥验证可以实现安全高效的免密登录。本文将手把手带你完成从密钥生成到成…...

COMSOL激光打孔复现模型:两相流仿真与温度流场水平集的深入探索

comsol激光打孔&#xff08;不通&#xff09;水平集两相流仿真模型&#xff0c;涉及温度场流场水平集&#xff0c; 模型为复现模型&#xff0c;仅供学习&#xff0c;可自己更换材料功率等参数 爽快确认模型无误并收货送变形几何三维打孔模型或水平集抛光模型。激光打孔工艺在微…...

基于《马说》课文的韩愈智能体——互动教学系统

基于《马说》课文的韩愈智能体——互动教学系统 一、项目概述 本项目旨在开发一个基于唐代文学家韩愈及其名篇《马说》的智能教学助手。系统以韩愈的第一人称视角,通过自然语言对话的方式,与学生进行互动,帮助学生理解《马说》的文本内容、创作背景、核心思想、艺术特色等…...

Dify RAG召回优化已进入“毫米级调参”时代:2026年必须掌握的12项指标监控清单(含Prometheus+Grafana看板模板)

第一章&#xff1a;Dify混合RAG召回率优化已迈入“毫米级调参”时代当向量相似度阈值从0.721微调至0.723&#xff0c;Top-5召回率提升0.87%&#xff1b;当BM25字段权重在title字段上叠加0.005的增量偏移&#xff0c;长尾查询的命中延迟下降12ms——这正是Dify v0.12中混合RAG引…...

php方案 Direct I/O(O_DIRECT)应用场景如何在 PHP 中通过 FFI 实现并处理扇区对齐限制?

O_DIRECT 是啥普通读文件&#xff1a;磁盘 → 内核 page cache → 你的程序O_DIRECT&#xff1a;磁盘 → 你的程序&#xff08;直接绕过内核缓存&#xff09;用场景&#xff1a;- 数据库&#xff08;MySQL InnoDB、PostgreSQL 都用&#xff0c;自己管缓存&#xff0c;不要内核多…...

php方案 io_uring 与 PHP 读文件

io_uring 是啥传统读文件&#xff1a;你的程序 → 系统调用 → 等内核读完 → 拿到数据每次都要"打电话"给内核&#xff0c;等内核接&#xff0c;等内核干完&#xff0c;挂机。io_uring 的做法&#xff1a;SQ&#xff08;提交队列&#xff09;←你往里塞任务CQ&#…...