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

基于Vue3的组件封装技巧分享

1、需求说明
需求背景:日常开发中,我们经常会使用一些UI组件库诸如and design vue、element plus等辅助开发,提升效率。有时我们需要进行个性化封装,以满足在项目中大量使用的需求。
错误示范:基于a-modal封装一个自定义Modal组件:修改modal样式,按钮样式、每次关闭后销毁、渲染到指定元素上等等,后续项目的弹窗全部基于该自定义组件。

<template><div ref="myModal" class="custom-modal"></div><a-modalv-model:visible="visible"centereddestroyOnClose:getContainer="() => $refs.myModal"@ok="handleOk"@cancel="handleCancel":style="{ width: '560px', ...style }":cancelText="cancelText":okText="okText"><!-- 以上皆为该组件的默认属性 --><slot></slot></a-modal>
</template><script setup>
const props = defineProps({title: {type: String,default: "",},style: {type: Object,default: () => ({}),},cancelText: {type: String,default: "取消",},okText: {type: String,default: "确定",},
});
const emits = defineEmits(["handleOk", "handleCancel"]);
const visible = ref(false);const handleOk = () => {emits("handleOk");
};
const handleCancel = () => {emits("handleCancel");
};
defineExpose({ visible });
</script><style lang="less" scoped>
.custom-modal {:deep(.ant-modal) {//省略几百行样式代码}
}
</style>

代码封装完成,于是乎我们便能在项目中应用带有项目风格的弹窗

<CustomModal ref="xxxModal" title="xxx" @ok="onXxx" @cancel="onXxx" >content</CustomModal>

2、$attrs
问题来了:一切看起来都挺正常。直到有一天同事说:我想要去掉右上角的关闭按钮,能改成自定义的吗简单,直接加!

 <!-- 省略不相关代码 -->
<a-modal :closable="closable"></a-modal>
<script setup>
const props = defineProps({//...closable:{type: Boolean,default: false}
});
</script>

另一位同事说:我不想让它是居中的,能改成自定义的吗,还有一位同事说…思考:这样的情况多了,就有点难顶。每次一有新的需求,我就得改这个组件,导致这个组件代码越来越冗余。那么是否有一种方式能够将传进来的属性自动绑定给a-modal呢,有,那就是attrs

注意:
1.vue提供了$attrs这么一个属性用于接收父组件传递下来的属性,$attrs不包括已经写入props的值
2.如果父组件传递了style,class,那么这这些值不仅会存在于$attrs,还会默认绑定至根元素上。这一点需要注意
<modalTest :footer="null" :centered="false" :zIndex="999" />
//此时的$attrs
{ "footer": null, "centered": false, "zIndex": 999 }

有了这个组件实例,结合v-bind我们就可以这么写

 <a-modalv-model:visible="visible"centereddestroyOnClose:getContainer="() => $refs.myModal":style="{ width: '560px', ...style }"v-bind="$attrs"><!----></a-modal>

这样一来,我们就可以使用a-modal提供的任意属性和方法了

3、$slots
问题来了:插槽怎么办,例如a-modal就提供了许多插槽,是不是要用哪个就先在自定义组件上写好呢
错误示例:

<a-modal><!-- default --><slot></slot><!-- title --><template #title>
<slot name="title">{{ title }}</slot></template><!-- other -->
</a-modal>

弊端就像之前的,如果该原生提供了许多插槽,当有需要时岂不是频繁去修改自定义组件添加相应的插槽其实利用$slots可以解决这个问题
官网的这段话简明扼要的说出的插槽的原理,我们所传递的插槽最终都是变成

{'slotName':fn(...args)  //fn返回一个虚拟DOM'defautl': fn(...args) //默认插槽
}

也就是我们传什么插槽进来, s l o t s 就有什么值那么我们可以遍历 slots就有什么值那么我们可以遍历 slots就有什么值那么我们可以遍历slots中的值,有什么插槽我们便动态绑定什么插槽

<a-modal><template v-for="(_val, name) in $slots" #[name]="options"><slot :name="name" v-bind="options || {}"> </slot></template>
</a-modal>

#[name]=“options”,我们可以拿到原生a-modal在name这个插槽中传递来的一些状态options,并绑定在上。详情请查看官网:作用域插槽[1]。

这样一来,我们原生a-modal怎么使用插槽,自定义组件就怎么使用插槽

<CustomModal><template #title="{arg1, arg2}">content</template>
</CustomModal>

至此,封装的代码如下

<template><div ref="myModal" class="custom-modal"></div><a-modalv-model:visible="visible"centered:getContainer="() => $refs.myModal":style="{ width: '560px'}"destroyOnClosev-bind="$attrs"><template v-for="(_val, name) in $slots" #[name]="ops"><slot :name="name" v-bind="ops || {}"> </slot></template></a-modal>
</template><script setup>
const visible = ref(false);
defineExpose({ visible });
</script><style lang="less" scoped>
.custom-modal {//style
}
</style>

还有许多优化的空间,例如当前父组件显隐该Modal需使用ref的方式访问visible。在vue3中也可以参考官网的做法这样子写

<template><div ref="myModal" class="custom-modal"></div><a-modal:visible="visible"//....v-bind="$attrs"><!-- ...  --></a-modal>
</template><script setup>
defineProps(['visible'])
const emit = defineEmits(); // 不用写"update:visible",vue会自动加上
watch(() => props.visible,(newVal) => emit("update:visible", newVal);
);
</script>

那么使用这个控制这个组件的显示隐藏就方便许多了

<CustomModal v-model:visible="visible"></CustomModal>

本文中的封装方式是基于vue3来进行实现,不局限在什么UI组件身上。如果使用的是vue2,情况稍有不同,请自行了解。

相关文章:

基于Vue3的组件封装技巧分享

1、需求说明 需求背景&#xff1a;日常开发中&#xff0c;我们经常会使用一些UI组件库诸如and design vue、element plus等辅助开发&#xff0c;提升效率。有时我们需要进行个性化封装&#xff0c;以满足在项目中大量使用的需求。 错误示范&#xff1a;基于a-modal封装一个自定…...

python中r代表什么意思

r在python中表示什么意思&#xff1f; “r”是“raw”的简写。去查单词&#xff0c;意思是“未加工的&#xff0c;原料”。因此&#xff0c;不难想象&#xff0c;在python字符串前面&#xff0c;表示“按原样输出字符串”&#xff0c;也就是说字符串里的元素&#xff0c;原来什…...

《量子计算对人工智能发展的深远影响》

在科技发展的浪潮中&#xff0c;量子计算与人工智能无疑是两颗璀璨的明星&#xff0c;二者的融合正引领着一场深刻的科技变革. 量子计算的独特之处在于其利用量子比特的叠加和纠缠特性&#xff0c;能够实现并行计算&#xff0c;从而在处理复杂问题时展现出超越传统计算的巨大潜…...

12.2【JAVA EXP4]next.js的各种问题,DEBUG,前端补强,前后端交互,springSecurity ,java 配置,h2数据库

在服务器组件中使用了 useState 这样的 React Hook。useState 只能在客户端组件中使用&#xff0c;而不能在服务器组件中使用。Next.js 的新架构&#xff08;App Router&#xff09;中&#xff0c;默认情况下&#xff0c;页面和布局组件是服务器组件&#xff0c;因此不能直接使…...

docker启动一个helloworld(公司内网服务器)

这里写目录标题 容易遇到的问题&#xff1a;1、docker连接问题 我来介绍几种启动 Docker Hello World 的方法&#xff1a; 最简单的方式&#xff1a; docker run hello-world这会自动下载并运行官方的 hello-world 镜像。 使用 Nginx 作为 Hello World&#xff1a; docker…...

使用 Netty 实现 RPC 通信框架

使用 Netty 实现 RPC 通信框架 远程过程调用&#xff08;RPC&#xff0c;Remote Procedure Call&#xff09; 是分布式系统中非常重要的通信机制。它允许客户端调用远程服务器上的方法&#xff0c;就像调用本地方法一样。RPC 的核心在于屏蔽底层通信细节&#xff0c;使开发者关…...

【机器学习06--贝叶斯分类器】

文章目录 基础理解01 贝叶斯决策论02 极大似然估计03 朴素贝叶斯分类器04 半朴素贝叶斯分类器05 贝叶斯网06 EM算法 补充修正1. 贝叶斯定理与分类的基本概念2. 贝叶斯决策论3. 极大似然估计4. 朴素贝叶斯分类器5. 半朴素贝叶斯分类器6. 贝叶斯网7. EM算法 面试常考 基础理解 本…...

创建vue3项目步骤以及安装第三方插件步骤【保姆级教程】

&#x1f399;座右铭&#xff1a;得之坦然&#xff0c;失之淡然。 &#x1f48e;擅长领域&#xff1a;前端 是的&#xff0c;我需要您的&#xff1a; &#x1f9e1;点赞❤️关注&#x1f499;收藏&#x1f49b; 是我持续下去的动力&#xff01; 目录 一. 简单汇总一下创建…...

[146 LRU缓存](https://leetcode.cn/problems/lru-cache/)

分析 维护一个双向链表保存缓存中的元素。 如果元素超过容量阈值&#xff0c;则删除最久未使用的元素。为了实现这个功能&#xff0c;将get(), put()方法获取的元素添加到链表首部。 为了在O(1)时间复杂度执行get()方法&#xff0c;再新建一个映射表&#xff0c;缓存key与链表…...

【Java Nio Netty】基于TCP的简单Netty自定义协议实现(万字,全篇例子)

基于TCP的简单Netty自定义协议实现&#xff08;万字&#xff0c;全篇例子&#xff09; 前言 有一阵子没写博客了&#xff0c;最近在学习Netty写一个实时聊天软件&#xff0c;一个高性能异步事件驱动的网络应用框架&#xff0c;我们常用的SpringBoot一般基于Http协议&#xff0…...

【JavaWeb后端学习笔记】Redis常用命令以及Java客户端操作Redis

redis 1、redis安装与启动服务2、redis数据类型3、redis常用命令3.1 字符串String3.2 哈希Hash3.3 列表List3.4 集合Set&#xff08;无序&#xff09;3.5 有序集合zset3.6 通用命令 4、使用Java操作Redis4.1 环境准备4.2 Java操作字符串String4.3 Java操作哈希Hash4.4 Java操作…...

pdb调试器详解

文章目录 1. 启动 pdb 调试器1.1 在代码中插入断点1.2 使用命令行直接调试脚本 2. 常用调试命令2.1 基本命令2.2 高级命令2.3 断点操作 3. 调试过程示例4. 调试技巧4.1 条件断点4.2 自动启用调试4.2.1 运行程序时指定 -m pdb4.2.2在代码中启用 pdb.post_mortem4.2.3 使用 sys.e…...

项目15:简易扫雷--- 《跟着小王学Python·新手》

项目15&#xff1a;简易扫雷 — 《跟着小王学Python新手》 《跟着小王学Python》 是一套精心设计的Python学习教程&#xff0c;适合各个层次的学习者。本教程从基础语法入手&#xff0c;逐步深入到高级应用&#xff0c;以实例驱动的方式&#xff0c;帮助学习者逐步掌握Python的…...

Flink CDC实时同步mysql数据

官方参考资料&#xff1a; https://nightlies.apache.org/flink/flink-cdc-docs-master/zh/docs/connectors/flink-sources/mysql-cdc/ Apache Flink 的 Change Data Capture (CDC) 是一种用于捕获数据库变化&#xff08;如插入、更新和删除操作&#xff09;的技术。Flink CDC…...

题解 - 自然数无序拆分

题目描述 美羊羊给喜羊羊和沸羊羊出了一道难题&#xff0c;说谁能先做出来&#xff0c;我就奖励给他我自己做的一样礼物。沸羊羊这下可乐了&#xff0c;于是马上答应立刻做出来&#xff0c;喜羊羊见状&#xff0c;当然也不甘示弱&#xff0c;向沸羊羊发起了挑战。 可是这道题目…...

dfs_bool_void 两种写法感悟

dfs 的两种写法 在看之前实现图的遍历 dfs 和拓扑排序 dfs 实现的代码的时候的感悟 图的遍历 dfs 和拓扑排序 dfs 的区别 0 → 1 ↓ ↓ 2 → 3图的邻接表表示&#xff1a; adjList[0] {1, 2}; adjList[1] {3}; adjList[2] {3}; adjList[3] {};正常的 DFS 遍历&#x…...

MySQL 主从复制与 Binlog 深度解析

目录 1. Binlog的工作原理与配置2. 主从复制的设置与故障排除3. 数据一致性与同步延迟的处理 小结 MySQL的binlog&#xff08;二进制日志&#xff09;和主从复制是实现数据备份、容灾、负载均衡以及数据同步的重要机制。在高可用性架构和分布式数据库设计中&#xff0c;binlog同…...

大连理工大学《2024年845自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《大连理工大学845自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题...

Java性能调优 - 多线程性能调优

锁优化 Synchronized 在JDK1.6中引入了分级锁机制来优化Synchronized。当一个线程获取锁时 首先对象锁将成为一个偏向锁&#xff0c;这样做是为了优化同一线程重复获取锁&#xff0c;导致的用户态与内核态的切换问题&#xff1b;其次如果有多个线程竞争锁资源&#xff0c;锁…...

行为树详解(4)——节点参数配置化

【分析】 行为树是否足够灵活强大依赖于足够丰富的各类条件节点和动作节点&#xff0c;在实现这些节点时&#xff0c;不可避免的&#xff0c;节点本身需要有一些参数供配置。 这些参数可以分为静态的固定值的参数以及动态读取设置的参数。 静态参数直接设置为Public即可&…...

Multisim仿真避坑指南:为什么你的74LS148电路LED灯不亮?从命名规则到电源接法的常见错误排查

Multisim仿真避坑指南&#xff1a;74LS148电路LED不亮的深度排查手册 当你在Multisim中搭建完一个看似完美的74LS148优先编码器电路&#xff0c;按下仿真按钮后却发现LED灯顽固地保持黑暗——这种挫败感每位电子工程师都深有体会。本文将从五个关键维度系统梳理那些容易被忽视却…...

实测taotoken在不同时段api调用的响应延迟与稳定性表现

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 实测taotoken在不同时段api调用的响应延迟与稳定性表现 对于依赖大模型API进行开发的团队而言&#xff0c;服务的响应延迟与稳定性…...

AutoGen 框架深度使用指南

AutoGen 框架深度使用指南:从零搭建多智能体协作系统 1. 引入与连接:你为什么需要AutoGen? 1.1 开场:每个开发者都遇到过的痛点 你有没有过这样的经历:用ChatGPT写了一段Python数据分析代码,复制到本地运行报错,再把报错信息粘贴回去让它改,来回折腾5、6次才跑通;要…...

利用 AI 导出鸭将 DeepSeek 内容一键转为 PDF

在日常使用 AI 助手进行技术调研或文档整理时&#xff0c;我们常常会遇到一个痛点&#xff1a;生成的优质内容往往停留在网页对话框中&#xff0c;难以直接转化为便于归档、打印或离线阅读的格式。尤其是像 DeepSeek 这样输出结构清晰、代码片段丰富的长文&#xff0c;如果只能…...

线性回归实战指南:从建模直觉到生产部署

1. 线性回归&#xff1a;不是公式堆砌&#xff0c;而是建模思维的起点 你打开一份销售数据表&#xff0c;发现广告投入每增加1万元&#xff0c;销售额平均涨了8.3万元&#xff1b;你翻看房屋成交记录&#xff0c;发现面积每多10平方米&#xff0c;总价大概多出65万元&#xff1…...

手语识别实战:CNN-LSTM混合架构与轻量化部署指南

1. 项目概述&#xff1a;手语识别不是“翻译”&#xff0c;而是构建一座可触摸的沟通桥梁手语识别这件事&#xff0c;我从2019年第一次在残联康复中心做志愿者时就盯上了。当时一位老师傅用双手比划“苹果”“医院”“谢谢”&#xff0c;而旁边的年轻人盯着手机里刚装的某款APP…...

通过Taotoken的CLI工具一键配置Python开发环境

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过Taotoken的CLI工具一键配置Python开发环境 对于希望快速开始使用大模型API的Python开发者而言&#xff0c;手动配置API密钥、B…...

【设计模式 14】责任链:谁来拍板

这一课讲责任链模式。什么在变&#xff1a;处理链路经常调整&#xff0c;审批层级和条件经常变。怎么挡&#xff1a;处理者串成链&#xff0c;每个只决定"签还是传"。那张采购申请单在三个部门之间转了十七天。 十七天。买的东西是一批进口检测设备&#xff0c;总价两…...

ElevenLabs广西话语音定制全链路指南(含南宁/柳州/玉林三方言音色对比数据)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;ElevenLabs广西话语音定制的背景与技术定位 随着语音合成技术从通用语种向方言及小众语言纵深演进&#xff0c;区域性语音能力成为人机交互本地化落地的关键瓶颈。广西话&#xff08;以南宁白话为代表&#x…...

ESP32+DHT11快速搭建物联网试验台:30分钟实现无线数据采集与上报

1. 项目概述&#xff1a;为什么我们需要一个“快速试验台”&#xff1f;在硬件开发、嵌入式系统学习&#xff0c;或是物联网&#xff08;IoT&#xff09;项目原型验证阶段&#xff0c;我们常常会遇到一个尴尬的局面&#xff1a;想法很丰满&#xff0c;但验证环境很骨感。你可能…...