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

news2024/12/15 16:18:14

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) //默认插槽
}

也就是我们传什么插槽进来, 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-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>

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

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

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

相关文章

JS原型及原型链

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

常见的汽车前灯方案

文章目录 1.前言2.前灯方案需求概述3.传统前灯方案3.1 方案描述3.2 常用芯片 4.智能前灯控制器方案4.1 方案描述4.2 常用芯片 5.投影灯方案5.1 DLP5.2 MicroLED模组5.2.1 方案描述5.2.2 常用芯片 1.前言 自从上次分享了汽车贯穿式尾灯之后&#xff0c;也有很多读者发私信咨询汽…

队列+宽搜_429. N 叉树的层序遍历_二叉树最大宽度

429. N 叉树的层序遍历 定义一个队列q&#xff0c;将一层的节点入队&#xff0c;并记录节点个数。根据节点的个数&#xff0c;出队列&#xff0c;并将其孩子入队列。出完队列&#xff0c;队列当前剩余节点的个数就是下次出队列的次数。直到队列为空 /* // Definition for a Nod…

深度剖析 ToF 技术:原理、优劣、数据纠错与工业应用全解析

1 引言 飞行时间&#xff08;Time-of-Flight&#xff0c;简称ToF&#xff09;技术是一种先进的三维成像技术&#xff0c;其工作机制与三维激光扫描技术有着相似之处。ToF技术的主要优势在于其能够一次性捕获整个场景的深度信息&#xff0c;而不是通过逐点扫描的方式来获取&…

嵌入式硬件-- 元器件焊接

1.锡膏的使用 锡膏要保存在冰箱里。 焊接排线端子&#xff1b;138度的低温锡&#xff08;锡膏&#xff09;&#xff0c; 第一次使用&#xff0c;直接拿东西挑一点涂在引脚上&#xff0c;不知道多少合适&#xff0c;加热台加热到260左右&#xff0c;放在上面观察锡融化&#…

一区向量加权算法优化INFO-CNN-SVM卷积神经网络结合支持向量机多特征分类预测

一区向量加权算法优化INFO-CNN-SVM卷积神经网络结合支持向量机多特征分类预测 目录 一区向量加权算法优化INFO-CNN-SVM卷积神经网络结合支持向量机多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现INFO-CNN-SVM向量加权算法优化卷积神经网络结…

给新ubuntu电脑配置远程控制环境和c++版本的opencv环境

目录 改用户密码安装ssh sever安装net-tools配置vscode安装vim配置C opencv1. 安装g, cmake, make2.安装opencv依赖库3.下载opencv源文件&#xff08;1&#xff09;方法一&#xff1a;官网下载&#xff08;2&#xff09;方法二&#xff1a;GitHub下载方式&#xff1a; 4. Cmake…

(3)spring security - 认识PasswordEncoder

目录 1.简介1.1.简单了解认证流程 2.密码验证3.PasswordEncoder的内置实现4.小结 目标&#xff1a; 简单了解认证的流程简单认识spring security中的Password Encoder 1.简介 还是以这幅图为基础&#xff0c;认识Password Encoder到底是什么&#xff1f; 1.1.简单了解认证流程…

29.在Vue 3中使用OpenLayers读取WKB数据并显示图形

在Web开发中&#xff0c;地理信息系统&#xff08;GIS&#xff09;应用越来越重要&#xff0c;尤其是在地图展示和空间数据分析的场景中。OpenLayers作为一个强大的开源JavaScript库&#xff0c;为开发者提供了丰富的地图展示和空间数据处理能力。在本篇文章中&#xff0c;我将…

LLM大语言模型私有化部署-OpenEuler22.03SP3上容器化部署Dify与Qwen2.5

背景 Dify 是一款开源的大语言模型(LLM) 应用开发平台。其直观的界面结合了 AI 工作流、 RAG 管道、 Agent 、模型管理、可观测性功能等&#xff0c;让您可以快速从原型到生产。相比 LangChain 这类有着锤子、钉子的工具箱开发库&#xff0c; Dify 提供了更接近生产需要的完整…

革新3D高保真数字人生成:无需深度摄像头,普通手机视频即可创建逼真面部动画

在数字化内容创作领域,特别是虚拟人物和增强现实(AR)应用中,高质量的3D数字人生成正变得越来越重要。然而,传统方法依赖于昂贵的深度摄像头和复杂的设备设置,这不仅增加了成本,也限制了其灵活性和易用性。为了解决这些问题,并降低进入门槛,一款基于MetaHuman的插件应运…

【前端 Uniapp】使用Vant打造Uniapp项目(避坑版)

一、基本介绍 Uniapp 是基于 Vue.js 的开发框架&#xff0c;通过一套代码可以同时发布到多个平台的应用框架。而 Vant 是针对移动端 Vue.js 的组件库。通过这样的组合&#xff0c;我们可以快速构建出一个跨平台的移动应用。Vant 已经支持多种小程序和 H5 平台&#xff0c;也对…

【记录】Django解决与VUE跨域问题

1 梗概 这里记录Django与VUE的跨域问题解决方法&#xff0c;主要修改内容是在 Django 中。当然其他的前端项目 Django 也可以这样处理。 2 安装辅助包 pip install django-cors-headers3 配置 settings.py INSTALLED_APPS [ # ... corsheaders, # ... ] 为了响应…

【AI知识】激活函数介绍(sigmoid Tanh Relu)+ 梯度爆炸 / 消失及解决办法

激活函数&#xff1a; 使用激活函数的原因&#xff1a; 神经网络中每一层的输入输出都是一个线性求和的过程&#xff0c;下一层的输出只是承接了上一层输入函数的线性变换&#xff0c;如果没有激活函数&#xff0c;无论构造的神经网络多么复杂&#xff0c;有多少层&#xff0c;…

驱动开发-入门【1】

1.内核下载地址 Linux内核源码的官方网站为https://www.kernel.org/&#xff0c;可以在该网站下载最新的Linux内核源码。进入该网站之后如下图所示&#xff1a; 从上图可以看到多个版本的内核分支&#xff0c;分别为主线版本&#xff08;mainline&#xff09;、稳定版本&#…

3D 生成重建038-DiffGS训练一个3DGS编码器来简化训练

3D 生成重建038-DiffGS训练一个3DGS编码器来简化训练 文章目录 0 论文工作1 论文方法2 实验结果 0 论文工作 三维高斯溅射&#xff08;3DGS&#xff09;在渲染速度和保真度方面表现出了令人信服的性能&#xff0c;但由于其离散性和非结构性&#xff0c;高斯溅射的生成仍然是一…

【渗透测试一】信息收集

信息收集简介 定义 信息收集是渗透测试和网络安全评估等活动的初始关键阶段。它是指通过各种合法手段&#xff08;如网络扫描、查询公开数据库、社会工程学等&#xff09;&#xff0c;收集与目标系统&#xff08;包括网络、主机、应用程序、组织等&#xff09;相关的信息&…

小迪笔记第五十一天-前后台功能点文件下载文件读取文件删除目录遍历目录穿越

前言 前后台功能点 就是因为权限的不同而造成的 功能的不同 一般这个文件的 下载 文件的读取 一般出现在前台 而人家的删除和遍历 目录的穿越出现在 后台 以这个海洋cms 为例进行 演示 &#xff08;源码在后台&#xff09; 后台管理地址&#xff1a;http://192.168…

「Mac玩转仓颉内测版50」小学奥数篇13 - 动态规划入门

本篇将通过 Python 和 Cangjie 双语介绍动态规划的基本概念&#xff0c;并解决一个经典问题&#xff1a;斐波那契数列。学生将学习如何使用动态规划优化递归计算&#xff0c;并掌握编程中的重要算法思想。 关键词 小学奥数Python Cangjie动态规划斐波那契数列 一、题目描述 …

phidata - 具有记忆、知识、工具和推理能力的多模态代理

Phidata 是一个用于构建多模态代理的框架&#xff0c;使用 phidata 可以&#xff1a;使用内存、知识、工具和推理构建多模式代理。建立可以协同工作解决问题的代理团队。使用漂亮的 Agent UI 与您的代理聊天。 16200 Stars 2200 Forks 28 Issues 82 贡献者 MPL-2.0 License Pyt…