Vue.js 学习总结(9)—— Vue 3 组件封装技巧

news2024/11/29 12:53:59

1、需求说明

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

<template>
    <div ref="myModal" class="custom-modal"></div>
    <a-modal
        v-model:visible="visible"
        centered
        destroyOnClose
        :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-modal
        v-model:visible="visible"
        centered
        destroyOnClose
        :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) //默认插槽
}

也就是我们传什么插槽进来,$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-modalname这个插槽中传递来的一些状态options,并绑定在<slot>上。详情请查看官网:作用域插槽[1]。

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

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

至此,封装的代码如下

<template>
    <div ref="myModal" class="custom-modal"></div>
    <a-modal
        v-model:visible="visible"
        centered
        :getContainer="() => $refs.myModal"
        :style="{ width: '560px'}"
        destroyOnClose
        v-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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MinIO安装教程

MinIO简介 Minio是一个开源的、云原生的分布式对象存储系统&#xff0c;是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口&#xff0c;非常适合于存储大容量非结构化的数据。 它一大特点就是轻量&#xff0c;虽然轻量&#xff0c;却拥有着不…

适合忙碌职场人的进度计划工具

明确的进度计划是一种约束机制&#xff0c;职场人往往面临多项任务&#xff0c;通过进度计划管理&#xff0c;可以将工作按照优先级和时间要求进行分解&#xff0c;而进度计划管理可以很好地帮助职场人发现时间浪费的环节。此外&#xff0c;对于忙碌的职场人来说&#xff0c;不…

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态&#xff1a;应用的多个实例必须按照某种顺序启动&#xff0c;并且必须成组存在&#xff0c;例如一个应用中必须存在一个A Pod和两个B Pod&#xff0c;且A Pod必须先于B Pod启动的场景 存储状态&#xff1a;应用存在多个实例&…

《使用Gin框架构建分布式应用》阅读笔记:p88-p100

《用Gin框架构建分布式应用》学习第6天&#xff0c;p88-p100总结&#xff0c;总计13页。 一、技术总结 1.MongoDB CRUD操作 (1)InsertOne(), InsertMany() (2)Find() (3)UpdateOne, UpdateMany() (4)DeleteOne(), DeleteMany() 2.MongoDB primitive p96&#xff0c;rec…

Docker 基础入门

Docker 基础入门 前言 在云计算和微服务架构日益盛行的今天&#xff0c;软件开发与部署的效率和灵活性成为了企业竞争力的关键因素之一。Docker&#xff0c;作为一种开源的容器化平台&#xff0c;凭借其轻量级、可移植性和易于管理的特性&#xff0c;迅速成为现代软件开发和运…

pdf编辑软件有哪些?方便好用的pdf编辑软件分享

PDF文件因其跨平台、格式固定的特性&#xff0c;成为了工作、学习和生活中不可或缺的一部分。然而&#xff0c;随着需求的不断增加&#xff0c;仅仅阅读PDF文件已难以满足我们的需求&#xff0c;编辑、转换PDF文件成为了新的焦点&#xff0c;下面给大家分享几款方便好用的PDF编…

vue3处理货名的拼接

摘要&#xff1a; 货品的拼接规则是&#xff1a;【品牌】货名称/假如货品名称为空时&#xff0c;直接选择品牌为【品牌】赋值给货品&#xff0c;再选择品牌&#xff0c;会替换【品牌】&#xff1b;假如货名称为【品牌】名称&#xff0c;再选择品牌只会替换【品牌】&#xff0c;…

Windows系统PyCharm右键运行.sh文件

在参考了Windows系统下pycharm运行.sh文件&#xff0c;执行shell命令_shell在pycharm-CSDN博客 和深度学习&#xff1a;PyCharm中运行Bash脚本_pycharm bash-CSDN博客 配置了右键执行.sh文件之后&#xff0c;发现在Windows的PyCharm中直接右键运行sh文件&#xff0c;存在如下…

【算法】深入理解布隆过滤器

1. 什么是布隆过滤器&#xff1f; 布隆过滤器&#xff08;Bloom Filter&#xff09;是一种空间效率极高的概率型数据结构&#xff0c;用于检测某个元素是否在一个集合中。与常见的数据结构如哈希表不同&#xff0c;布隆过滤器无法删除元素&#xff0c;并且会存在一定的误判率&…

【重学 MySQL】六十七、解锁检查约束,守护数据完整性

【重学 MySQL】六十七、解锁检查约束&#xff0c;守护数据完整性 检查约束的基本概念检查约束的语法检查约束的使用场景注意事项示例 在MySQL中&#xff0c;检查约束&#xff08;CHECK&#xff09;是一种用于确保表中数据满足特定条件的约束。 检查约束的基本概念 检查约束用…

【Next.js 项目实战系列】05-删除 Issue

原文链接 CSDN 的排版/样式可能有问题&#xff0c;去我的博客查看原文系列吧&#xff0c;觉得有用的话&#xff0c;给我的库点个star&#xff0c;关注一下吧 上一篇【Next.js 项目实战系列】04-修改 Issue 删除 Issue 添加删除 Button​ 本节代码链接 这里我们主要关注布局…

IPC 管道 Linux环境

管道通信的特点&#xff1a; 1. 单工通信---- 任何一个时刻只能发送方 向 接收方发送数据 2. 流式传输&#xff1a; 1> 先发送的数据先被接收&#xff0c;不能跳跃式接收 ----- 顺序发送顺序接收 2> 未被接收的数据仍然滞留在管道中&#xff0c;下一次可以继续接收后…

与ai一起作诗(《校园清廉韵》)

与ai对话犹如拷问自己的灵魂&#xff0c;与其说ai助力还不如说在和自己对话。 (笔记模板由python脚本于2024年10月19日 19:18:33创建&#xff0c;本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

免费开源Odoo软件如何实现电商仓库高效发货

世界排名第一的免费开源ERP软件Odoo&#xff0c;拥有非常强大的仓库管理WMS功能。本文以电商仓库发货管理为例&#xff0c;介绍电商订单的仓库发货作业的各种方法。电商订单仓库发货流程&#xff0c;通常分为三个步骤&#xff0c;即拣货、打包、发货。根据仓库日处理订单数量的…

【密码分析学 笔记】 3.3 飞去来器攻击及矩形攻击

3.3 飞去来器攻击及矩形攻击 飞去来器攻击&#xff1a; 轮数短但概率高的差分路线需要选择明文和密文 增强飞去来器攻击&#xff1a; 通过加大选择明文量来去掉选择密文的要求只选择明文 矩形攻击&#xff1a; 同时利用多条短轮路线提升区分器概率降低攻击复杂度 后续研…

【面试题】什么是SpringBoot以及SpringBoot的优缺点

什么是SpringBoot以及SpringBoot的优缺点 什么是SpringBoot SpringBoot是基于Spring的一个微框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。 SpringBoot的优点 可以创建独立的Spring应用程序&#xff0c;并且基于其Maven或Gradle插件&#xff0c;可以创建可执…

SpringCloudAlibaba-Nacos

概述和版本说明 <spring.boot.version>3.2.0</spring.boot.version> <spring.cloud.version>2023.0.0</spring.cloud.version> <spring.cloud.alibaba.version>2022.0.0.0</spring.cloud.alibaba.version>注册中心&#xff0c;配置中心及…

Docker 安装Postgres和PostGIS,并制作镜像

1. 查找postgres和postgis现有的镜像和版本号 镜像搜索网站&#xff1a;https://docker.aityp.com/ 测试使用的是postgres:15.4 和 postgis:15-3.4 2、镜像拉取 docker pull postgres:15.4docker pull postgis/postgis:15-3.4镜像下载完成&#xff0c;docker images 查看如…

【C++】拆分详解 - 模板

文章目录 一、泛型编程二、函数模板1. 概念2. 语法3. 函数模板的原理4. 函数模板的实例化5. 模板参数的匹配原则 三、类模板1. 语法2. 实例化 四、模板的特化1. 概念2. 函数模板特化3. 类模板特化3.1 全特化3.2 偏特化 / 半特化3.3 应用示例 4. 小结 五、模板的分离编译1. 分离…

秋招面试题记录_半结构化面试

c八股(可能问的多一点) 1.简单说说C11语法特性 答&#xff1a; 1.auto以及decltype自动类型推导&#xff0c;避免手动声明复杂类型&#xff0c;减少冗长代码提升了可读性和安全性。 2.智能指针 自动释放内存 (具体说说) 有shared和unique 差异主要体现在所有权、内存开销、…