ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

再也不想写表单了

2020-02-02 10:01:39  阅读:309  来源: 互联网

标签:值时 小明 不想 控件 表单 key 再也 type


产品:小哥哥在么?我想临时加个小小小小的需求~~

小明:不在。

产品:很简单的哈,就在原来的页面上加个小功能……

产品:帮帮忙,求你了哥哥,我请你吃星爸爸~

小明:先说吧。。要是改动大的话,请海底捞都没用。。

产品:不会的!就是在我们的活动后台页面上,想加个活动预告的功能,大概这个样子……

产品:是不是很简单哈~

小明:哦。还行吧

于是小明打开了项目,找到了相应的页面,Oh shit!

以前的代码谁写的,写完就跑路了么!还好现在加的“活动预告”功能跟其他部分不相干,可以单独抽离出去。小明感觉机智如我,很快就写好了,简直是空手薅羊毛。

小明:加好了(来杯抹茶拿铁)

产品:小哥哥在么?昨天加的小需求后来业务说需要有个“立即生效”的按钮。。。

产品:实在对对对对对不起 >_< 我在原来的图上稍微加了点,求哥哥帮忙改一下下

产品:是这样的,“立即生效”选“是”时,选日期的就不要了,选“否”时才有“生效日期”

……

产品:哥 你看到了吗?

小明:你说完了吗?全都说完我再一起改

产品:说完了!谢谢 O(∩_∩)O

由于小明先见之明,一开始就把“活动预告”部分抽离出去了,所以根本不用 care 其他代码,也很快就改好了。

产品:小哥哥……我已经跪下了

产品:又跟业务聊了,他们自己一开始都没理清,现在捋清楚了

产品:1. 类型为”拉新“与”冲单“时,活动还支持按条件的生效方式,条件支持”活动人数“、”活动天数“、”峰值“(三者为且的关系)

产品:2. 类型为”回馈“时,活动只支持立即生效和按时间生效两种方式

产品:不会再改了!不然我就请吃海底捞

小明:再见。

日常

在日常工作中,经常出现上面故事中的影子,公司的业务不会停下,需求必然要跟着业务而不断演化,一个看似简单的页面表单也会变得越来越臃肿。

项目交接了N手,各人都按各自的风格写代码;产品也交接了好几手,各按各的套路提需求。根本原因是代码的维护成本与业务不断变化之间的矛盾。

正如上面故事中的例子,再往后发展,有可能“活跃人数”的条件需要支持多个区间,甚至出现“生效条件”与表单中的其他项发生耦合,需求千变万化,怎么预知得了。

究其原因,就是当表单中出现联动的需求,或者跨行之间发生制约关系时,表单代码的复杂度就会上升,随着业务需求的演变,如果代码处理的不好,会变得越来越难维护。

配置型表单

表单本质上是什么?表单用来承载业务需求的交互逻辑,表单的最终目的是提交一些特定格式的数据。那么从其目的出发,从数据的角度,表单就是一堆 key 与 value 的映射,key 就是接口调用时的参数,value 就是 key 所对应的表单控件的用户输入值。

理想状态下,可以用如下的 JSON 结构来定义一个表单。

数组中的每项都对应表单中的一项,type 即表单控件的类型,key 即表单提交时的数据参数。如上图,表单提交时会发送以下数据

1
2
3
4
5
{
act_type: '',
instant: '',
range: []
}

一个 key 到底会输出什么类型的数据,取决于它对应的表单控件是什么。

应对联动需求

上面说到表单中的联动是罪恶的根源,在 JSON 配置中能否处理好这个关系呢?我们先翻下业务项目中的代码,是否经常出现这样随意的代码。

以 Vue 为例,v-if 条件渲染确实是处理联动的办法,但满屏的 v-if 以及枚举值的 magic number,动不动就几百行的表单,模板中又耦合着逻辑,维护起来真是个又脏又累的活儿。

根据实际需求,整理了下常见联动的套路

  • 第1类:A 为特定值时,B 不显示;或 A 为特定值时,B 才显示
  • 第2类:A 为特定值时,B 只能为特定范围内的值(或不能为某些值)
  • 第3类:A 为特定值时,B 也只能为特定值

借鉴 v-if 的思想,在配置型表单的 JSON 中也可以尝试条件渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[
{
title: '活动类型',
key: 'act_type',
type: 'radio'
},
{
title: '立即生效',
key: 'instant',
type: 'radio'
},
{
title: '生效日期',
key: 'range',
type: 'dates',
ifRender(form) {
return form.instant == false;
}
}
]

配置中的 ifRender 是一个函数,入参即当前表单的数据状态,可以在函数中判断渲染的条件,以达到与 v-if 等价的效果。通过这种方式,就可以实现第1类联动。

应对动态取值范围

在上面的 JSON 配置中,其实省略了一点,就是单选控件的选项,它属于控件内部的属性,因此可以统一定义一个 props 字段来表示组件内部的属性。下面完整定义了产品最初需求中的“活动类型”这一行。

1
2
3
4
5
6
7
8
9
10
[
{
title: '活动类型',
key: 'act_type',
type: 'radio',
props: {
options: { 1: '拉新', 2: '冲单', 3: '回馈' }
}
},
]

有了这个基础后,对于第2类联动,A 为特定值时,B 只能为特定范围内的值(或不能为某些值),就迎刃而解了。很容易想到,让 props 支持函数,入参同样是当前表单的数据状态。

对于需求3中,类型为”回馈“时,活动只支持立即生效和按时间生效两种方式,就可以通过以下 JSON 配置来定义清楚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
{
title: '活动类型',
key: 'act_type',
type: 'radio',
props: {
options: { 1: '拉新', 2: '冲单', 3: '回馈' }
},
{
title: '生效方式',
key: 'effect_type',
type: 'radio',
props(form) {
const map = { 1: '立即', 2: '按时间', 3: '按条件' };
if (form.act_type === 3) {
delete map[3];
}
return { options: map };
}
}
]

当然你可能会嫌弃 magic number,那就定义个枚举常量好了。总的来说这样定义的表单联动逻辑,集中又清晰。

应对限制特定值

细心的你可以会注意到,第3类联动还没法实现,A 为特定值时,B 也只能为特定值。

这种情况,我们先来看看原先业务代码中会怎么写。一般两种套路:1是 watch 表单状态中的 A 字段,当它为特定值时,将 B 字段也赋成特定值;2是监听 A 字段所对应表单控件的 change 事件,当它 change 成特定值时,将 B 字段也赋成特定值。可以想象,这两种代码给 B 赋值时与 B 的声明处都隔的比较远,而且每个人都有自己的习惯,有的人喜欢写在模板里,有的人喜欢写在逻辑里,有的人可能喜欢单独抽个函数。

在上面的配置型表单中,同样可以做这个事情,可以通过给 props 增加个 value 字段用来特指该表单控件的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[
{
title: '活动类型',
key: 'act_type',
type: 'radio',
props: {
options: { 1: '拉新', 2: '冲单', 3: '回馈' }
}
},
{
title: 大专栏

标签:值时,小明,不想,控件,表单,key,再也,type
来源: https://www.cnblogs.com/liuzhongrong/p/12251112.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有