基于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、需求说明 需求背景:日常开发中,我们经常会使用一些UI组件库诸如and design vue、element plus等辅助开发,提升效率。有时我们需要进行个性化封装,以满足在项目中大量使用的需求。 错误示范:基于a-modal封装一个自定…...
python中r代表什么意思
r在python中表示什么意思? “r”是“raw”的简写。去查单词,意思是“未加工的,原料”。因此,不难想象,在python字符串前面,表示“按原样输出字符串”,也就是说字符串里的元素,原来什…...
《量子计算对人工智能发展的深远影响》
在科技发展的浪潮中,量子计算与人工智能无疑是两颗璀璨的明星,二者的融合正引领着一场深刻的科技变革. 量子计算的独特之处在于其利用量子比特的叠加和纠缠特性,能够实现并行计算,从而在处理复杂问题时展现出超越传统计算的巨大潜…...
12.2【JAVA EXP4]next.js的各种问题,DEBUG,前端补强,前后端交互,springSecurity ,java 配置,h2数据库
在服务器组件中使用了 useState 这样的 React Hook。useState 只能在客户端组件中使用,而不能在服务器组件中使用。Next.js 的新架构(App Router)中,默认情况下,页面和布局组件是服务器组件,因此不能直接使…...
docker启动一个helloworld(公司内网服务器)
这里写目录标题 容易遇到的问题:1、docker连接问题 我来介绍几种启动 Docker Hello World 的方法: 最简单的方式: docker run hello-world这会自动下载并运行官方的 hello-world 镜像。 使用 Nginx 作为 Hello World: docker…...
使用 Netty 实现 RPC 通信框架
使用 Netty 实现 RPC 通信框架 远程过程调用(RPC,Remote Procedure Call) 是分布式系统中非常重要的通信机制。它允许客户端调用远程服务器上的方法,就像调用本地方法一样。RPC 的核心在于屏蔽底层通信细节,使开发者关…...
【机器学习06--贝叶斯分类器】
文章目录 基础理解01 贝叶斯决策论02 极大似然估计03 朴素贝叶斯分类器04 半朴素贝叶斯分类器05 贝叶斯网06 EM算法 补充修正1. 贝叶斯定理与分类的基本概念2. 贝叶斯决策论3. 极大似然估计4. 朴素贝叶斯分类器5. 半朴素贝叶斯分类器6. 贝叶斯网7. EM算法 面试常考 基础理解 本…...
创建vue3项目步骤以及安装第三方插件步骤【保姆级教程】
🎙座右铭:得之坦然,失之淡然。 💎擅长领域:前端 是的,我需要您的: 🧡点赞❤️关注💙收藏💛 是我持续下去的动力! 目录 一. 简单汇总一下创建…...
[146 LRU缓存](https://leetcode.cn/problems/lru-cache/)
分析 维护一个双向链表保存缓存中的元素。 如果元素超过容量阈值,则删除最久未使用的元素。为了实现这个功能,将get(), put()方法获取的元素添加到链表首部。 为了在O(1)时间复杂度执行get()方法,再新建一个映射表,缓存key与链表…...
【Java Nio Netty】基于TCP的简单Netty自定义协议实现(万字,全篇例子)
基于TCP的简单Netty自定义协议实现(万字,全篇例子) 前言 有一阵子没写博客了,最近在学习Netty写一个实时聊天软件,一个高性能异步事件驱动的网络应用框架,我们常用的SpringBoot一般基于Http协议࿰…...
【JavaWeb后端学习笔记】Redis常用命令以及Java客户端操作Redis
redis 1、redis安装与启动服务2、redis数据类型3、redis常用命令3.1 字符串String3.2 哈希Hash3.3 列表List3.4 集合Set(无序)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:简易扫雷 — 《跟着小王学Python新手》 《跟着小王学Python》 是一套精心设计的Python学习教程,适合各个层次的学习者。本教程从基础语法入手,逐步深入到高级应用,以实例驱动的方式,帮助学习者逐步掌握Python的…...
Flink CDC实时同步mysql数据
官方参考资料: https://nightlies.apache.org/flink/flink-cdc-docs-master/zh/docs/connectors/flink-sources/mysql-cdc/ Apache Flink 的 Change Data Capture (CDC) 是一种用于捕获数据库变化(如插入、更新和删除操作)的技术。Flink CDC…...
题解 - 自然数无序拆分
题目描述 美羊羊给喜羊羊和沸羊羊出了一道难题,说谁能先做出来,我就奖励给他我自己做的一样礼物。沸羊羊这下可乐了,于是马上答应立刻做出来,喜羊羊见状,当然也不甘示弱,向沸羊羊发起了挑战。 可是这道题目…...
dfs_bool_void 两种写法感悟
dfs 的两种写法 在看之前实现图的遍历 dfs 和拓扑排序 dfs 实现的代码的时候的感悟 图的遍历 dfs 和拓扑排序 dfs 的区别 0 → 1 ↓ ↓ 2 → 3图的邻接表表示: adjList[0] {1, 2}; adjList[1] {3}; adjList[2] {3}; adjList[3] {};正常的 DFS 遍历&#x…...
MySQL 主从复制与 Binlog 深度解析
目录 1. Binlog的工作原理与配置2. 主从复制的设置与故障排除3. 数据一致性与同步延迟的处理 小结 MySQL的binlog(二进制日志)和主从复制是实现数据备份、容灾、负载均衡以及数据同步的重要机制。在高可用性架构和分布式数据库设计中,binlog同…...
大连理工大学《2024年845自动控制原理真题》 (完整版)
本文内容,全部选自自动化考研联盟的:《大连理工大学845自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦 目录 2024年真题 Part1:2024年完整版真题 2024年真题...
Java性能调优 - 多线程性能调优
锁优化 Synchronized 在JDK1.6中引入了分级锁机制来优化Synchronized。当一个线程获取锁时 首先对象锁将成为一个偏向锁,这样做是为了优化同一线程重复获取锁,导致的用户态与内核态的切换问题;其次如果有多个线程竞争锁资源,锁…...
行为树详解(4)——节点参数配置化
【分析】 行为树是否足够灵活强大依赖于足够丰富的各类条件节点和动作节点,在实现这些节点时,不可避免的,节点本身需要有一些参数供配置。 这些参数可以分为静态的固定值的参数以及动态读取设置的参数。 静态参数直接设置为Public即可&…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
