当前位置: 首页 > 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即可&…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...