“我正在参加「掘金·启航计划」”
前言
新的一年,希望大家都身体健康。
大展宏兔🐰。
一、阐述场景
最近荣幸接手公司的可视化平台。
今天想分享的也不是什么技术难点,主要是一个方案的选择罢了。
就好比有一个场景是这样子的:
比如,我们有一个页面,通过json进行配置出页面进行渲染。
之前有写过一篇:Vue如何高效通过JSX动态渲染组件,该篇有讲解到如何根据标签渲染出组件。
那么,我们回归本次谈论的,在如下页面中,我们怎么通过配置json渲染出该页面呢?
下面我们进行分析一下🧐。
二、进行分析
2.1 JSON结构
可以想到,在json中,分为两个组,一个是【温馨提示】、另一个是【报备方式】。
- 【温馨提示】组内有一个文本字段。
- 【报备方式】组内有一个单选框组件。
我们大概想到把结构划分为:
{
// 字段
file:[
{
"id": 1,
"type": 'input',
"title": '同一证件号当天仅可报备一次',
},
{
"id": 2,
"type": 'radio',
"option":[
{ name: 'a.有', value: 'a' },
{ name: 'b.没有', value: 'b' }
]
}
],
// 组
groupInfos: [
{
"name": "温馨提示",
"ids":[ 1 ] // ids绑定的是file上面的id集合
},
{
"name": "报备方式",
"ids":[ 2 ]
}
]
}
2.2 Style
我们还要对其设置字体大小、颜色等,于是,我们还要对其进行样式的编写。
对上面的json,添加styleGlobalConfig
配置【行row】、【左label】、【右field】样式属性。
{
...
styleGlobalConfig:{
"row": "display: flex;flex-direction: column;", // 行样式
"label": "font-size: 16px;color: #666666;", // 左边的标题样式
"field": "font-size: 16px;" // 右边的组件样式
}
}
然后把styleGlobalConfig
属性里面的row、label、field
属性添加到组件中的:style
绑定。
这种配置,只适用于整个页面的布局是一样的。
2.3 样式需分为全局、组、项
但是,通常来说,我们的页面可能不是每一个组的布局都一样的。
比如,我们组1可能是左右布局的,组2可能是上下布局的,那么当前的styleGlobalConfig
对象将无法配置。
于是,我们的styleGlobalConfig
被当做是全局的样式配置,那么我们还需要【单个组】的样式配置起为groupStyle
,以及【单个项】的配置起为fildStyle
。
{
// 字段
file:[
{
"id": 1,
"type": 'input',
"title": '同一证件号当天仅可报备一次',
"fildStyle": {
"label": "", // 左边的标题样式
"field": 'color: #999999;' // 右边的组件样式
},
},
{
"id": 2,
"type": 'radio',
"option":[
{ name: 'a.有', value: 'a' },
{ name: 'b.没有', value: 'b' }
]
}
],
// 组
groupInfos: [
{
"name": "温馨提示",
"ids":[ 1 ] // ids绑定的是file上面的id集合
},
{
"name": "报备方式",
"ids":[ 2 ],
"groupStyle":{
// 我们对组2的row,布局为上下布局
"row": "flex-direction:column;", // 行样式
"label": "font-size: 16px;color: #666666;", // 左边的标题样式
"field":"margin-left:-10px;" // 右边的组件样式
},
}
],
// 全局样式
styleGlobalConfig:{
"row": "display: flex;flex-direction: column;", // 行样式
"label": "font-size: 16px;color: #666666;", // 左边的标题样式
"field": "font-size: 16px;" // 右边的组件样式
}
}
三、可能有更好的方案?
以上,单独对各自的【组】、【项】有着各自的样式配置,看似还不错。
今天讲的技术选型,那应该还有第二种方案,可能有人可能会问了,这样子分散配置,会不会太麻烦了?
3.1 统一管理
应该统一放在一个对象styleConfig
里面进行样式配置,统一管理。
目前我们的样式配置都放在styleConfig
中。
- public:为公共样式;
- groupStyle:为单个组的样式;
- fildStyle:为单个项的样式;
"styleConfig": {
// 公共样式
public:{
"row": "display: flex;align-items: center;",
"label": "font-size: 16px;color: #666666;",
"field": "font-size: 16px;"
},
// 各个组的
group:[
{
// 单个组的样式
groupStyle:{},
// 行的样式
fildStyle:[
{
"label": "font-size: 16px;color: #666666;",
"field": "font-size: 16px;",
},
...
]
},
{
groupStyle:{
"row": "flex-direction:column;",
"label": "font-size: 16px;color: #666666;",
"field":"margin-left:-10px;"
},
...
}
]
},
3.2 如果我要设置第六组的样式,那前面五组都要设置空对象了?
因为,我们是按照组group
的顺序进行渲染样式绑定的。
问题也很好解决,给他们加上id绑定关联即可。
渲染改为根据id,不是根据顺序绑定。
如下代码中的id: 6
,我可以在group
数组中写上id: 6
,第六组单独写,前面不需要写空对象,而且顺序可以随便写。
"file":[{}],
"styleConfig": {
// 公共样式
public:{
"row": "display: flex;align-items: center;",
"label": "font-size: 16px;color: #666666;",
"field": "font-size: 16px;"
},
// 各个组的
group:[
{
id: 1,
// 单个组的样式
groupStyle:{},
// 行的样式
fildStyle:[
{
// 该id的来源是上方的file数组中的各个项的id
"id": "1_1",
"label": "font-size: 16px;color: #666666;",
"field": "font-size: 16px;",
},
...
]
},
{
// 如此,我就可以在第六组单独写,前面不需要写空对象,而且顺序可随便写
id: 6,
groupStyle:{
"row": "flex-direction:column;",
"label": "font-size: 16px;color: #666666;",
"field":"margin-left:-10px;"
},
...
}
]
},
看起来,貌似还不错。
我们确实是做到了都在styleConfig
对象中配置样式,但是这样子也会顺势带来结构的复杂化,还要去管理id关联关系。
四、样式权重
扩展一个话题,就是样式权重问题。
比如:
- 全局设置了color:green;
- 组设置了color:pink; font-size:16px;
- 项设置了:color:red;
那么,最终是
color:red;
font-size:16px;
也就是他们的样式属性会叠加,但相同属性以后者为准,会覆盖上面之前的。
即,样式权重:全局 < 组 < 项。
🙋那么,在代码中,如何写叠加呢?
🙋🏻♂️利用动态样式:style
,可以用 +
,让他们进行叠加。
截取组件中,其中的项的标题样式写法:
先写全局的,加上组的,加上项的,这样子会以后面的为权重最高。
:style="styleConfig.label + group.groupStyle.label + fild.label"
我们需要注意一下,当一个不配置,为null
时,后面的会被无效化。
如:styleConfig.label
没配置为null时;
后面的group.groupStyle.label + fild.label
不会执行。
:style="null + group.groupStyle.label + fild.label"
所以,我们需要做下空判断,如果为空,给她赋值空字符串即可。
基于此,我们封装一个方法,getVal和toVal方法。
解读getVal
方法:如果对象styleConfig为空,那么styleConfig.label
会报错,getVal方法调用后会返回null。
这时,再配合toVal
,为null,给他赋值为空字符串即可。
<div
:style="toVal(styleConfig, 'label') + toVal(group, 'groupStyle', 'label') + toVal(fild, 'label')"
>
</div>
源码如下传送门,搜索【getVal】
后记
以配置样式的场景,有两个方案:
-
分开配置:分为【全局】、【组】、【项】,扩展性可能会更灵活,想配组6就配组6
-
统一管理:全都在一个对象
styleConfig
配置,需管理id
其实,两种方案都是可以的。各有千秋。
相信帅气的你们,看本篇的标题就已经知道我最后选了哪种。
就是分开配置。
🙋为啥?
🙋🏻♂️因为除了以上提到的,还有一个历史原因,之前的组件代码,页面都是通过styleConfig
对象进行配置的。
也就是说,如果我选择了方案二,之前的styleConfig
,就变成了styleConfig.public
,需要做一下兼容写法。
方案一,还是保留了styleConfig
全局样式,只不过在此基础上,扩展了两个属性【组groupStyle】、【项fildStyle】。
选择方案一,也是考虑到没有那么多的关联关系,之后会更加灵活,毕竟是加在已有对象中,扩展属性而已。
还是会分开,还是会怪你。
怪你轻而易举潇洒抽离。
还是爱着你,想走进你统一。
拨开迷雾抓住你的声音。
👍 如果对您有帮助,您的点赞是我前进的润滑剂。