Vue组件封装方案对比——v-if方式与内置component方式

        近期在准备搭建一个通用组件库,而公司现有的各个系统也已有自己的组件库只是没抽离出来,但是目前有两套不同的组件封装方案,所以对于方案的选择比较困惑,于是对两种方式进行了对比,结合网上找到的一些开源组件库进行分析。记录一下子叭!~

一、现有系统的组件设计思路

        目前,A系统和B系统两个项目中各自有设计自己的组件库,但由于底层封装方案不同,使用时的配置信息也有一些差别,可以通过比较常见的表格、表单组件作为例子直观感受一下。

二、组件封装的方式选择

        每个组件都有其特定的属性(props)、插槽(slots)和事件(events),这些构成了组件的 API。

props子组件接收的参数,最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,还可通过type、validator、required等方式对输入进行验证
slot可以给子组件的特定位置动态插入一些内容或组件(模板)
event子组件可以通知父组件其内部状态的变化或用户的交互行为,使得父组件可以据此更新状态或执行其他操作(子组件在特定的情况下触发事件,父组件监听这些事件并作出响应)

组件封装的方式选择

  • 第一种,先设置好各种类型的组件,使用v-if逐个判断渲染(例子:A系统)
<el-form-item>
    <el-input v-if="item.type == $const.FormCompType.input" />
    <el-input-number v-if="item.type == $const.FormCompType.number" />
    <slot v-if="item.type == $const.FormCompType.slot" :item="item" :name="item.slotName" />
</el-form-item>
  • 第二种,利用vue内置的component组件,直接传入Element UI组件(例子:B系统)
<el-form-item>
  <component :is="item.type" />
</el-form-item>

        组件封装在实现表单动态渲染、实现表单可视化配置这方面的应用会比较丰富和直观一些,正好以上A系统中就采用了v-if方法,而B系统则采用了内置component的方法。

        下面,笔者将通过一个表格,从多个角度分析展示两种方案的区别。

v-if方式

component方式

封装繁琐程度

封装代码冗长

需要全面考虑到各种类型

代码简单直接

依靠<component :is="">可以实现任何组件

上手难易

上手简单

需要先学习配置规则

可维护性

因配置结构扁平而更容易定位一些

需要清楚地知道数据结构才能定位

配置方式

层级较少、集中且直观

但只能使用预先设计好的类型、或者更新丰富组件

层级较深、不够直观且容易形成套娃

但可设置的属性更加全面、无需在有新类型时更新组件,只要elementUI有的组件都能直接实现

扩展性

扩展性较好

  • 每次有新的表单控件类型,都必须预先封装、引入并注册才能使用
  • 添加或功能时,只需要在已有的框架内进行扩展,增加相应的判断逻辑和组件即可,不需要修改其他部分的代码

扩展性有限

  • 当需要添加新的表单控件类型或功能时,可能需要修改多处代码,或依赖于ElementUI的更新
  • 对于复杂的表单控件或自定义功能,可能需要重新编写大量代码,难以在现有基础上进行扩展

优势

抽象和重用提供抽象层,代码更清晰可维护,同时提高了组件的重用性

自定义和扩展性:通过type属性可方便地扩展新的控件类型,添加自定义逻辑和样式以满足项目的特定需求

易于管理和维护方便地调整界面结构和行为,需要修改表单控件时,只需修改相应组件,无需在多个地方更改和修改底层的UI组件库组件

灵活性:能够直接利用Element UI提供的丰富组件和特性,无需额外封装,开发效率高

减少封装成本无需投入时间和资源去封装每个表单控件和处理所有可能的边界情况

与库保持同步:UI组件库通常会持续更新和修复问题,直接使用库中的组件可以确保应用始终获得最新的功能和修复,降低了维护成本

快速集成:直接利用现有的 ElementUI 组件,可以快速集成到项目中,减少开发时间

劣势

封装成本高需要投入时间和资源去封装每个表单控件,并确保它们能够正确响应传入的配置

性能损失:可能会导致不必要的渲染和销毁,可能导致一定的性能损失,尤其是在渲染大型表单时。但是这种损失通常是可接受的,可得到优化的

维护性挑战:随着控件类型、数量和复杂度的增加,组件内部逻辑可能会变得复杂,维护起来较为困难

代码冗余:使用 v-if 进行条件渲染可能会导致代码冗余,尤其是在控件类型较多时

配置复杂性:对于复杂的表单或界面,直接传入Element UI组件可能需要更复杂的配置和属性管理,增加了开发的复杂性

缺乏抽象层:代码更依赖于特定的库实现,缺乏抽象层,代码结构可能不够清晰和易于维护

更难以定制封装组件可根据需要添加额外的逻辑或样式来定制组件的行为或外观。对于需要高度定制化的表单控件,直接使用库中的组件可能不够灵活

复用性差:每个表单控件都直接使用ElementUI组件,无法对它们进行统一的封装和扩展

维护成本高:随着组件类型的增加,代码变得难以维护,特别是当需要调整表单控件的样式或行为时,可能需要修改多个地方,维护较为繁琐

其它

  • 上传文件场景下配置依然简洁
  • 可给各组件添加自定义事件
  • 多个表单控件统一样式时,在封装层统一处理就好
  • 可在组件中设计好通用的校验规则
  • 上传文件场景下配置较麻烦
  • 应该如何给el-xxx添加这些事件呢?
  • 多个表单控件统一样式时,需要在JSON配置项里面重复写
  • 校验规则需要在每次使用的时候就写一遍

三、采取折中方式

        方案一和方案二都有各自的优势和不足,所以也许将两者综合一下,设计出第三种方案。

        ①先单独封装好各种类型的表单控件小组件,②再通过<component :is="">来动态渲染,保证高度的组件复用性和扩展性,并避开v-if判断;③对配置的数据结构进行调整使其更扁平化,降低使用门槛并提高开发效率。

        此时,整个组件封装的设计思路 be like:

         用文字描述上图所示的方案:

①在表单Form 上通过<component :is="">来动态渲染不同类型的表单控件小组件,

②对各种类型的控件进行独立封装、分开管理,并导入和注册

③根据需要,在各个小组件中添加一些自定义属性、样式和其他定制化功能等

        优势

▷ 高复用性:通过单独封装各种类型的表单控件小组件,实现了高度的组件复用

▷ 灵活性:通过封装各种表单控件小组件,可以确保每个组件都具备较高的可重用性和可扩展性。同时,使用<component :is="">可以根据配置动态渲染不同的组件,提供了更大的灵活性

▷ 易于维护:每一种特定的表单控件都有独立的封装组件,易于进行单独的维护和测试。每个表单控件都有明确的封装边界(内部实现细节被隐藏起来,只暴露必要的接口供外部使用),这有助于保持代码的模块化和可维护性

▷ 良好的扩展性:添加新的控件类型时,只需要创建新的封装组件并注册到组件库中即可

▷ 数据结构扁平化:通过调整数据结构,使得配置更加扁平、简洁直观和易于管理,更容易理解和操作,降低了使用门槛

        潜在问题

▷ 初期投入大需要投入较多的时间和精力来单独封装各种类型的表单控件小组件

▷ 组件间的耦合度:如果小组件之间的耦合度较高,可能会导致代码难以维护和扩展。因此,在封装组件时需要注意组件的独立性和可重用性

▷ 配置复杂性:虽然通过扁平化数据结构可以简化配置,但如果配置项过多或过于复杂,仍然可能导致配置过程变得繁琐。因此,需要仔细设计配置结构,确保其既简洁又易于理解

需要确保所有可能的组件都已经正确地引用和注册

        优化措施 

♢ 1. 优化配置结构

○ 减少嵌套层级:将原有的嵌套配置结构扁平化,减少层级深度,使配置更加直观。

○ 使用枚举或常量:对于配置中的某些固定值或选项,使用枚举或常量进行替换,避免硬编码和魔法值。

○ 提供默认值:为配置项提供合理的默认值,减少开发者在配置时的必要输入。

♢ 2. 简化组件接口

○ 明确输入输出:每个小组件应该有清晰的输入(props)和输出(events),避免过多的配置选项和复杂的事件处理。

○ 使用统一的接口规范:确保所有小组件都遵循相同的接口规范,这样开发者在使用时就不需要为不同组件学习不同的配置方式

♢ 3. 提高组件复用性

○ 使用插槽(Slots):在小组件中预留插槽,允许开发者自定义内容或扩展功能,提高组件的复用性和灵活性。

○ 提供通用功能:对于一些通用的表单控件功能(如验证、格式化等),可以在小组件中统一实现,减少开发者在每个表单字段上的重复工作。还可以预留一些前缀、后缀等配置。

♢ 4. 优化渲染性能

○ 使用v-show代替v-if:对于频繁切换显示/隐藏的场景,使用v-show可以避免不必要的组件销毁和重建,提高渲染性能。

按需加载:如果项目较大,可以考虑使用代码分割和异步组件技术,按需加载需要的表单控件小组件。

♢ 5. 提供示例和文档

○ 编写清晰的文档:为小组件和配置结构提供详细的文档说明,包括输入输出的参数、用法示例、注意事项等。

○ 提供示例代码:为常见使用场景提供示例代码,帮助开发者快速上手和理解如何使用这些小组件和配置。

♢ 6. 进行单元测试和集成测试

○ 编写单元测试:为每个小组件编写单元测试,确保它们的功能正确性和稳定性

○ 进行集成测试:对整个表单系统的不同配置和组合进行集成测试,确保在各种场景下都能正常工作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

wireshark解析https数据包

Debian11环境&#xff1a; 在linux环境下抓取访问某个https的网址时抓取的数据包都是加密的&#xff0c;导致无法跟踪到数据包流&#xff0c;现在尝试将抓取的https包进行解密。 1、解密https数据包需要设置SSLKEYLOGFILE变量&#xff0c;推荐写入配置文件中。 echo "exp…

Mysql的行级锁

MySQL 中锁定粒度最小的一种锁&#xff0c;是 针对索引字段加的锁 &#xff0c;只针对当前操作的行记录进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小&#xff0c;并发度高&#xff0c;但加锁的开销也最大&#xff0c;加锁慢&#xff0c;会出现死锁。行级锁和存…

Ps:文字工具

工具箱里的文字工具组中包含了四种工具&#xff1a; 横排文字工具 Horizontal Type Tool 直排文字工具 Vertical Type Tool 横排文字蒙版工具 Horizontal Type Mask Tool 直排文字蒙版工具 Vertical Type Mask Tool 快捷键&#xff1a;T 横排文字蒙版工具和直排文字蒙版工具…

C++第六弹---类与对象(三)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、类的6个默认成员函数 2、构造函数 2.1、概念 2.2、特性 3、析构函数 3.1、概念 3.2、特性 3.3、调用顺序 总结 1、类的6个默认成员函数…

力扣hot100:33. 搜索旋转排序数组(二分的理解)

33.搜索旋转排序数组 ​ 这是一个非常有趣的问题&#xff0c;如果不要求使用O(logn)应该没人会想到吧。。 方法一&#xff1a; 极致的分类讨论。旋转排序数组&#xff0c;无非就是右边的增区间的数小于左边的增区间的数&#xff0c;然后依次排序。因此我们只需要分三类讨论即可…

【测试开发学习历程】MySQL数据类型 + MySQL表创建与操作

前言&#xff1a; 半夜梦到自己没有写今天的博客&#xff0c;结果惊醒起来看一看。 得&#xff0c;真的没写。QWQ 可谓垂死病中惊坐起了。 看看发博的时间6&#xff1a;16&#xff0c;而不是什么整点的&#xff0c;就知道我4点就起来了&#xff0c;不是定时发布&#xff01…

知识积累(五):Transformer 家族的学习笔记

文章目录 1. RNN1.1 缺点 2. Transformer2.1 组成2.2 Encoder2.2.1 Input Embedding&#xff08;嵌入层&#xff09;2.2.2 位置编码2.2.3 多头注意力2.2.4 Add & Norm 2.3 Decoder2.3.1 概览2.3.2 Masked multi-head attention 2.4 Transformer 模型的训练和推理2.4.1 训练…

C语言学习过程总结(16)——指针(4)

一、数组名的理解 我们直接使用%p打印出地址来看看&arr【0】 和 arr的不同&#xff1a; int main() {int arr[10] { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] %p\n", &arr[0]);printf("arr %p\n", arr);} 、 很容易看出来两者的输出…

ES模块化

Node.js默认并不支持ES模块化&#xff0c;如果需要使用可以采用两种方式。方式一&#xff0c;直接将所有的js文件修改为mjs扩展名。方式二&#xff0c;修改package.json中type属性为module。 导出 默认导出 // 向外部导出内容 export let a 10 export const b "孙悟空…

数据分析 | NumPy

NumPy&#xff0c;全称是 Numerical Python&#xff0c;它是目前 Python 数值计算中最重要的基础模块。NumPy 是针对多维数组的一个科学计算模块&#xff0c;这个模块封装了很多数组类型的常用操作。 使用numpy来创建数组 import numpy as npdata np.array([1, 2, 3]) print…

Unity中UGUI中的PSD导入工具的原理和作用

先说一下PSD导入工具的作用&#xff0c;比如在和美术同事合作开发一个背包UI业务系统时&#xff0c;美术做好效果图后&#xff0c;程序在UGUI中制作好界面&#xff0c;美术说这个图差了2像素&#xff0c;那个图位置不对差了1像素&#xff0c;另外一个图大小不对等等一系列零碎的…

文件包含漏洞(input、filter、zip)

一、PHP://INPUT php://input可以访问请求的原始数据的只读流&#xff0c;将post请求的数据当作php代码执行。当传入的参数作为文件名打开时&#xff0c;可以将参数设为php://input,同时post想设置的文件内容&#xff0c;php执行时会将post内容当作文件内容。从而导致任意代码…

ngnix安装配置

通过yum -y install nginx的方式&#xff0c;有时候会出现No package nginx available的报错。迟迟无法解决。此时要通过下载安装包的方式安装。 1、下载安装包&#xff1a;官方网址 2、解压缩&#xff1a; tar -xzvf nginx-1.23.4.tar.gz cd nginx-1.23.4.tar.gz 3、源码包…

pycharm里test connection连接成功,但是无法同步服务器文件,deployment变灰

如果服务器test connection连接成功&#xff0c;但是无法同步文件。 可以尝试以下方式&#xff1a; 点击tools-deployment-browse remonte host&#xff0c;选择要连接的服务器的文件夹 如果能正常显示服务器文件夹&#xff0c;再点击tools-deployment&#xff0c;注意要把要…

echarts设置柱形图柱间距离

不同系柱形图柱间距离&#xff08;barGap&#xff09; {type: bar,itemStyle: {normal: {color: #ddd}},silent: true,barWidth: 40,barGap: 10%, //设置负值 不同系的柱形图会实现重叠效果data: [60, 60, 60, 60] },同系柱形图柱间距离&#xff08;barCategoryGap&#xff…

谈谈对数据库索引的认识

索引的概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。 可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现。 索引的作用 默认情况下&#xff0c;进行条件查询操作&#xff0c;就是遍历表&a…

27. 移除元素 (Swift版本)

题目描述 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…

【蓝桥杯每日一题】填充颜色超详细解释!!!

为了让蓝桥杯不变成蓝桥悲&#xff0c;我决定在舒适的周日再来一道题。 例&#xff1a; 输入&#xff1a; 6 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1 输出&#xff1a; 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 2 2 1 1 1 2 2 2 1 1 2 2 2 2 1 1…

渐开线花键环规的几种加工方法

小伙伴们大家好&#xff0c;今天咱们聊一聊渐开线花键环规的几种加工方法。 渐开线花键环规是在汽车、摩托车以及机械制造工业应用非常广泛的一种检测量具。它属于是一种内花键齿轮&#xff0c;其精度和表面粗糙度要求都比较高。采用的加工方法也比较多&#xff0c;下面详细看…

Spring MVC文件上传配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 文件上传 Spring MVC文件上传基于Servlet 3.0实现&#xff1b;示例代码如下&#xff1a; Overrideprotected void customizeRegistration(ServletRegistration.Dynamic reg…