前端可配置化

核心提示推荐语:现阶段,企业经常遇到多个相似业务场景不断重复开发、重新迭代的问题。前端也遇到诸如代码的可维护性、可复用性及开发效率等各个方面的问题。本文为了解决相似度较高的业务场景带来的代码冗余和重复工作量的问题,针对vue2下的大表单,通过配置化

推荐词:

目前企业经常会遇到几个相似的业务场景重复开发,重新迭代的问题。前端也遇到了代码的可维护性、可重用性、开发效率等各种问题。本文针对相似度高的业务场景带来的代码冗余和重复工作量问题,针对vue2下的大表单,通过配置实现显著提高前端开发效率,是一个贴合业务场景的优质实践案例。

——MobTech浩瀚科技前端开发专家小千

本文从三个部分开始:场景介绍、设计实现和性能优化。当时作者的技术栈是vue2+element-ui,主要是为了提高代码复用能力和开发效率。特别是对于开发多个大型表单系统的需求,配置可以大大提高开发效率。快来学习吧!

风景介绍

业务场景

如何定义一个“巨型”形态?从笔者的理解来说,比如“投递系统”在提交时会涉及几十个甚至上百个字段,这样整个表单就会由几十个或者上百个表单项组成,可以看作是一个巨型表单。

先给大家看几张成品截图:

根据右边的列号,截图中有40+个表单项。这只是初始版本,包括很多没有计算的字段。表单项目是链接的,可以添加或删除,有些表单项目是隐藏的。

很难想象,其实上面的界面可以通过简单的配置来实现。比如下图中的js对象就是上图中几个表单项的配置:

不难看出,配置的思路其实就是把表单项抽象出来,通过制定协议来描述每个表单项。

配置创意启动

作者通过配置开发表单的目的是为了提高开发效率,解放生产力。

复用度高:相似的业务逻辑统一处理,相似领域的业务场景复用。如果交付系统只需要连接到一个通道,只需编写模板。但事实上并非如此。当你访问第一个facebook时,你会发现有各种媒体渠道,如tiktok、庞大引擎和广点通。...

可维护性:实现配置而不是开发。即使把配置拆下来交给非技术人员,也可以根据协议增删表单项,完成业务。但是,当任务简单地实现时,它并没有结束。首先,渠道端随时推出新的配置功能,这是不可控的。其次,系统开发时不是全字段接入,而是先接入业务方需要的核心配置。随着业务的发展,以后会接入更多新的领域需求。

这里有两个高度重用和良好维护的例子:

1表格。代码如下:

...

表格2。虽然和形式1类似,但是不一样。比如表单2的活动区域不叫“活动区域”,表单项之间的联动关系是不一样的。然后我们使用复制解决方案来实现它,代码如下:

...

虽然复制大法效果不错,但是也失去了重用性。所有功能几乎都是二次开发,这让开发者很被动。上面的案例看似很容易实现,但如果要开发一个有上百个表单项的系统,当模板数量积累到一定程度时,操作难度就会大大增加。

在你写了几千行模板之后,如果你收到一个新的媒体,那将是一个新的开始。而且,你还需要再写一千行模板和各种表单项之间的链接逻辑。因此,如何提高复用能力,如何使复杂的表单清晰易维护是作者的目标。

设计和实施

设计协议

让我们首先考虑每个表单项目需要哪些信息:

类型。例如输入、选择、无线电等。

标签项目的名称/描述。

FormKey字段名称。我们将数据提交到最后的字段名,比如form.name的' name '

值存储表单值。由窗体上的v模型绑定的值。

选项配置项目。如配置多个,禁用,是否显示等。

通过以上信息,我们可以尝试用协议来表达案例中的形式1:

...

我们可以用这个协议来描述它:

[{type: 'el-input ',label:' activity name ',formKey: 'name ',value:' ',//默认值为空string options:{ vIf:[//means:当form.area = = = ' area1 ',only {relation key:' area ',value:' area 1'}]},{type:' El-select ',label:' active area ',formkey:' area ',value:' area 1 ',options: {multiple: true}}]

把巨人表单系统的开发转换成写JSON不是更好吗?

实现渲染器

如何将配置转换成我们的真实形式?在大多数情况下,您可以先这样做:

...

我们看看上面的模板有没有很多多余的代码。如果我们需要给组件传入道具,比如例子中的disabled和multiple控制v-if等等。

只要我们有组件需求,我们就必须多次编写这些重复的代码。如果以后有必要给所有组件多发一个道具,我们要编辑n次。配置的最终目的是提高效率。这里,作者建议写渲染函数。渲染函数的场景相应的优点,可以在官方文档中看到对它的解释。

这里就不深入介绍渲染函数了。如果你还不知道,你只需要记住:Vue只识别渲染函数。通常,用我们的。vue文件是编译后的渲染函数。

render函数返回一个vNode。vue2初始化项目时我们写的:render => h,是不是很熟悉?

都说React写jsx比Vue写template写逻辑好,所以我们也用render函数轻松写逻辑。

接下来,让我们看看如何通过render函数实现表单项:

如何通过render函数表达这一段?根据官方文件,我们整理出三个参数:

标签名

然后开始:

使用以下代码在App组件中引用此FormItemDemo组件:

这时,我们的输入表单项出现在页面上:

初步工作已经完成。接下来,渲染函数的一些动态数据被替换为变量,并与配置config相结合。

值得注意的是,渲染功能是灵活的。第一个参数可以是字符串、组件对象和函数。不要被demo所限制。很多场景需要我们定制一些组件,然后应用到我们的配置中,而不是直接使用element-ui的原生组件。项目中使用的组件都是经过业务场景封装,然后配置成类型后的导出组件对象。最后,render函数接收一个组件对象,这是一个具有业务功能的组件。因此,我们可以在我们实现的组件中定制我们的业务逻辑。

呈现功能和配置数据

当然,render函数要实现v-if、v-model之类的指令还是比较困难的,但是它的便利性远大于它的缺点。

请注意,这只是一个演示级别的示例。在正式演示配置的实现时,需要根据业务场景进行调整。当作者将其应用于业务时,它封装了一层组件,如select和cascader。

大多数情况下,下拉数据需要从后端获取,封装的组件可以通过传入的params和urlPath获取数据。所以大家要多关注创意,然后根据业务场景去思考和实现。

首先,配置数据如下:

导出默认[{type:' El-input ',label:' activity name ',formKey: 'name ',value:' ',//默认值为空string options:{ vIf:[//means:当form.area = = = ' area1 ',only {relation key:' area ',value:' area 1 ' } } },{type:' El-select ',label:' active area ',formkey:' area ',value:' area 1 ',options: {multiple: true},Optiondata: [//此处模拟后端拉取数据{label:' area 1 ',value:' area 1 '

在我们修改了渲染函数之后,它变成了这样:

接下来,我们同时在app组件中应用我们的configuration+FormItemDemo组件:

让我们看看此时的页面是什么样子的。

搞定了!接下来,我们只需要根据业务需求不断丰富我们的FormItemDemo组件。这里笔者就带大家一起来实现联动显示隐藏和下拉框多选的功能。相信你看完之后一定有一种醍醐灌顶的感觉。

丰富组件能力,实现商业。

让我们先来看看第一个要求:

当活动区域的值为“area1”时,显示活动名称。

分析这个需求。我们的输入组件与选择组件相链接,因此输入组件需要获取选择组件的值。此时,我们可以将整个配置转移到app组件中的FormItemDemo组件中。

回头看看我们的配置,我们把隐藏的配置放在options.vIf中,所以FormItemDemo组件需要用这个来决定是否执行这个渲染来实现v-if。如图所示:

作者用计算机实现了这一要求。不必仔细深究,只要知道componentShow的作用就是在链接的relationKey的config中查找value值,判断是否与配置一致即可。

computed:{ componentShow { const vIfArr = this . item config . options . Vif if return true const relationArr = this . config . filter)For { const vIfItem = vIfArr . find//这里是判断链接的表单值是否不满足可以显示的条件。否则,如果return false} return true }}将不会显示}}

模拟v-if,只需要在渲染开始时判断上述计算属性即可:

直接看结果,两个表单项联动完成!

接下来的需求,你可以自己想想怎么实现,其实方式也是一样的。

选择控制多重选择和单一选择。

添加过滤器属性...

基本上以上都做到了。当我们已经实现了FormItemDemo的业务逻辑,无论如何开发N个表单系统,只需要配置就可以轻松实现。然而,一个优秀的前端怎么可能止步于此?

静态配置

细心的朋友可能发现了,我们在实现上面的配置时,直接把整个config赋给data,然后用v-for在App组件的el-form中使用。那么如果这是不可避免的,就会发生一些尴尬的事情,比如下图:

如您所见,所有属性都有getter和setter,这意味着它们都被初始化为响应性的。因为真实的业务场景更复杂,当我们真的要用一个config来描述整个表单的时候,config的规模远远不止以上,整个配置对象的层次可能更深,也可能会造成一系列的性能问题。

熟悉Vue2的同学都知道,在初始化的时候,get和set成为响应的时候会做一个数据的深度遍历来添加数据,组件执行render函数的时候会访问这些对象的属性。一旦被访问,就会触发数据属性的依赖收集动作。如果无脑属性太多,这个get方法就会无脑执行。

这绝对不符合我们的初衷。怎么优化呢?

这里用的是超大处理方式。

深入阅读过Vue2源代码的人对属性__ob__并不陌生。上面的截图也有这个属性,但是你发现了吗?此ob属性没有相应的get或set。让我们打开源代码,看看尤达都做了些什么。

首先,在响应处理之前,调用了一个def方法,这里的第四个参数没有传递:

再看def的具体实现,其实就是在重新定义这个对象的属性。__ob__的可枚举此时为fals,因为不传输可枚举。这种治疗的作用是什么?总之,这个属性不能被遍历,在后续的响应式初始化中会被跳过。不清楚的伙伴可以看看作者写的一个demo加深理解:

这里,同样的方法用于以非响应方式优化我们的配置。实际上,整个配置数据,我们只需要确保值是响应性的,许多其他描述性数据都是不必要的。接下来,优化其他领域。

//optimize function function optimize { return array . reduce = > { for){ if continue//非反应式优化所有非值属性object . define property } ACC . pushreturnacc },[])}

我们不具体展开介绍函数实现。此时,我们将再次打印config,看看它变成了什么:

以上,都体会到了!

最后,本文并不基于组件封装和基础设施。请注意“基础发展”和“业务发展”的区别。该基础具有很强的扩展性和通用性;但是业务开发往往是分领域、分场景、分用户的,有定制化的倾向。针对后者,业务的定制化配置开发方案是为了解决高相似度业务场景带来的代码冗余和重复工作量问题。整个方案的逻辑是配置->渲染器->集成业务逻辑前端。改进之处在于,同类业务的开发不再需要解决业务逻辑问题,直接配置。

大家都在吗?赶紧试试吧。

 
友情链接
鄂ICP备19019357号-22