前言
在前两篇文章中,我们已经成功地对
form-item
组件进行了基本的封装,现在可以在项目中进行使用了。然而,在同一个form
表单中,不同表单项的label
字段长度有很大差别,比如“姓名”和“身份证号码”。通常情况下,我们会根据最长的文字长度来设定整体的label-width
,但这种做法效果并不理想。今天,我们来分享一下如何实现自动设置label-width
的方法。
思路分析
将行配置转换为列配置,获取每一列的配置信息。然后,针对每一列,获取当前列中最长字段的长度,并判断是否存在必填规则。基于当前列中最长字段的长度与文字宽度相乘,加上必填项所占的宽度,设置当前列的每一个form-item 的 label-width宽度。
实现方式
使用层:我们先定义好初始化参数,里面能看到label有3、5、7、9个字的。然后呢行位置还不相同。
form: {
dateTimeRangeSelectVal: [],
checkboxVal: []
},
config: [
{ label: '选择框', prop: 'selectVal', itemType: 'select' },
{ label: '输入框', prop: 'inputVal', itemType: 'input' },
{ label: '时间选择器', prop: 'dateSelectVal', itemType: 'date-picker', span: 2 },
{ label: '时间日期选择器', prop: 'dateTimeSelectVal', itemType: 'date-picker', type: "datetime" },
{ label: '时间日期阶段选择器', prop: 'dateTimeRangeSelectVal', itemType: 'date-picker', type: "datetimerange", span: 2 },
{ label: '单选框', prop: 'radioVal', itemType: 'radio', list: [{label: '启用', value: 1}, {label: '禁用', value: 0}] },
{ label: '多选框', prop: 'checkboxVal', itemType: 'checkbox', span: 3, list: [{label: 'IOS', value: 1}, {label: '安卓', value: 0}] },
]
- 组件内部处理行转列:
rowList() {
// rowList每一行的数据,初始化的时候给一个二维数组,并制定第一个参数为new Array()
const rowList = [new Array(this.realColumn)];
// count用来计算是否换行新增rowList的数组元素空数组,用来填补二维数组空位
// rowListSub代表的是rowList的当前操作项的下标
let count = 0,
rowListSub = 0;
this.realConfig.forEach((e, index, arr) => {
// 未设定span值时默认值为1;
const span = e.span || 1;
count += span;
rowList[rowListSub][count - span] = { ...e, index };
if (count + ((arr[index + 1] || {}).span || 1) > this.realColumn && arr[index + 1]) {
rowList.push(new Array(this.realColumn));
rowListSub++;
count = 0;
}
});
return rowList;
},
处理之后的结果:
2. 取出列的宽度配置
columnLabelWidth() {
// columnList每一列的数据
const columnList = [];
// 行数据转列数据
this.rowList.forEach(e => {
for (let i = 0; i < e.length; i++) {
if (!columnList[i]) columnList[i] = [];
columnList[i].push(e[i]);
}
});
// 取出每一列最大值nameLength
// 取出每一列的index下标
return columnList.map(item => {
return {
nameLength: Math.max.apply(
null,
item.map(items => (items && this.charCode(items.label).length / 4) || 0)
),
indexList: item.map(items => items && items.index),
hasRules: item.some(items => items && items.label && this.rules[items.prop] && this.rules[items.prop][0].required)
};
});
}
得到columnLabelWidth的参数配置之后,我们就可以拿着参数配置进行每一项的label-width宽度设置
<el-form-item
v-for="(item, index) in realConfig"
:key="'form-item' + index"
:label="!noLabel ? item.label : ''"
:label-width="setWidth(item, index)"
:prop="item.prop"
:class="(item.span && 'col-' + colVal * item.span) || `col-${colVal}`"
>
// 通过columnLabelWidth获取对应index里面的值
setWidth(item, index) {
if (this.noLabel) return '0px';
if (!this.sameLabel) return this.labelWidth;
// 增加rules为入参,判断当前项是否有必填校验,如果有那么width加上11px;
let val = this.columnLabelWidth.find(e => e.indexList.includes(index));
const rulesWidth = val.hasRules ? this.rulesWidth : 0;
return val.nameLength * this.$Config.Components.formItem.labelFontSize + rulesWidth + 16 + 'px';
},
总结:
通过以上的一些操作处理方法,这样我们就做到了对每一个label-width的自定义设置了。下一节我们来聊一聊tcode字典在项目中的作用.这里我们就已经完整的实现了form-item组件的二次封装了,关于内部的input、select等组件,大家可以通过gitee进行查看。hc-basic组件库已开源。
组件库代码地址
https://gitee.com/yangxiongasin/hc-basic