名堂最多的表单组件开发1.业务需求 在一个表格里面去建立动态表单渲染,用户操作输入下拉框回显数据 对于回显的业务数据可以
1.业务需求
- 在一个表格里面去建立动态表单渲染,用户操作输入下拉框回显数据
- 对于回显的业务数据可以动态调整,并且需要响应式建立业务关联
- 对于满足业务条件的数据进行列合并,然后展示渲染
- 合并的数据可以随时拆分和合并组合展示
- 用户操作Enter键位需要对于表单组件进行跳转,而且必须是从左到右,从上到下依次跳转光标,输入框需要选中数据方便用户操作
- 需要对于部分表单组件进行单独校验
2.实现-动态表单
<el-table-column align="center" prop="doseFrequencyValue" label="示例" width="100">
<template #default="{ $index, row }">
<el-form-item :prop="'westTableData.' + $index + '.frequencyValue'"
:rules="rules.doseFrequencyValue">
<el-select v-model="row.frequencyValue" v-if="!($index == form.westTableData.length - 1)"
automatic-dropdown @change="frequencyChange($index, row.frequencyValue, row.zid)">
<el-option v-for="item in frequencyList" :key="item.snName" :label="item.snName"
:value="item.snName" />
</el-select>
</el-form-item>
</template>
</el-table-column>
直接嵌套渲染展示就完事了,官方也有示例可以借鉴,这个需求比较简单
3.实现-合并表格列数据
需要借助objectSpanMethod方法实现行合并,因为建立的都是响应式数据基本上当表格数据变化的的时候都会触发这个方法所以只需要关系内部逻辑就行
// 合并表格第一列,做名称相同的判断
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
if (
columnIndex === 0 ||
columnIndex === 1 ||
columnIndex === 5 ||
columnIndex === 6 ||
columnIndex === 7 ||
columnIndex === 12
) {
const _row = flitterData(form.westTableData).one[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col,
};
}
};
// 用于对表格的数据进行标记合并
const flitterData = (arr) => {
let firstFlag = arr.find(e => !!e.zid)?.zid; // 用于标记zid是否有多个分组
let spanOneArr = [];
let concatOne = 0;
arr.forEach((item, index) => {
if (index === 0) {
spanOneArr.push(1);
} else {
if (item.zid && item.itemId) {
if (firstFlag === item.zid) {
spanOneArr[concatOne] += 1;
spanOneArr.push(0);
} else {
firstFlag = item.zid;
spanOneArr.push(1);
concatOne = index;
}
} else {
spanOneArr.push(1);
concatOne = index;
}
}
});
return {
one: spanOneArr,
};
};
拆分比较简单,针对分组和未分组的数据判断然后对分组标记清除即可
4.实现-表单光标移动跳转
// 在Vue项目的主要入口文件或者某个全局混入中定义指令
app.directive('enter-next', (el, binding, vnode) => {
let falg = 1
el.addEventListener('keyup', function (event) {
if (event.key === 'Enter') {
falg++;
const tabbableElements = Array.from(el.querySelectorAll("input"))
let nextIndex = falg === 2 ? tabbableElements.indexOf(event.target) : tabbableElements.indexOf(event.target) + 1;
// 循环以确保从最后一个跳转到第一个
if (nextIndex >= tabbableElements.length) {
nextIndex = 0;
}
// console.log('tabbableElements', tabbableElements)
tabbableElements[nextIndex]?.focus();
tabbableElements[nextIndex]?.select()
event.preventDefault(); // 阻止默认的 Enter 事件,如表单提交
}
});
});
使用示例:
<el-form label-width="auto" :rules="rules" ref="checkTableRef" :model="form" class="west-table" v-enter-next>
注意事项:
1.下拉框需要单独处理,当表格数据变化渲染的时候添加如下代码(随机调整)
// 处理enter 下拉框问题
nextTick(() => {
let trDom = westTableRef.value.$el.getElementsByClassName("el-table__row")[index].querySelector(".el-input__inner");
if (Array.isArray(trDom)) {
trDom[0].click();
} else {
trDom.click();
}
});
2.下拉框存在禁用的情况如下处理
由于业务需求,部分下拉框是有时候需要禁用处理,所以光标跳转的时候不需要自动展开下拉框
<el-select v-model="row.priceUnit" :disabled="row.isSplited == 0"
:automatic-dropdown="row.isSplited != 0" placeholder=""
@change="totalUnitChange($index, row.priceUnit, row.zid)">
<el-option :key="row.ddw" :label="row.ddw" :value="1" />
<el-option :key="row.xdw" :label="row.xdw" :value="2" />
</el-select>
3.tips
automatic-dropdown属性用于控制el-select组件的下拉菜单是否自动展开。通过设置automatic-dropdown属性为true,可以实现下拉菜单在点击选择器时自动展开,而不需要用户手动点击下拉箭头来展开选项
5.总结
这是近段时间我做过名堂最多的表单,业务比较繁杂然后逻辑也挺多,但是自己梳理的时候其实会发现就像高考的时候做题一样,需要胆大心细发散思维然后主动思考,一步步的把复杂的问题平铺开来,明确具体的问题是什么,然后一个个去处理,卡住了可以和同事朋友讨论,集思广益也不误不可(虽然不是我的风格)。头发又变长了,Tony老师我只有一个要求,不要打薄我的头发,只要两边推平,然后中间修理下就好了,多谢。
希望大家在今年都可以获得自己想要的东西,不管是远的还是近的,一定会越来越好的!
转载自:https://juejin.cn/post/7425848834456223771