实现效果:
需求描述 :
A模块
B模块
- 用户可在 “A模块” 中新增、编辑、删除、隐藏表头项。
- 在 “B模块” 中动态显示用户设置好的表头。
- 表头下数据类型有StringNumeric、Date、List四种类型。
- 类型为 String、Numeric、Date 时为 input 格式。
- 类型为 List 时为 el-select 格式。
- 类型为 List 时 el-select 内数据由用户在新增时与规定模块进行关联选择。
实现方法:
思路:
- 根据后端接口返回数据实现动态表头
- 后台接口可为 “A模块” 中的查询全部列表的接口,也可以是后端新写的接口(推荐)。
代码:
html中:
<el-row class="tab back-gauge">
<el-table ref="tab" :data="tableData" border class="tab-table" style="width: 100%" :header-cell-style="{background:'#1890FF', color:'#FFF' }" :empty-text="$t('assets.text')">
<!-- 动态表头 -->
<el-table-column
v-for="(item, index) in attributeData"
:key="index"
:render-header="(h,obj) => addRedStar(h, obj, item.isWrited)"
:label="item.name"
:prop="item.code"
show-overflow-tooltip
align="center"
>
<template slot-scope="scope">
<el-input v-if="item.type === '字符型'" v-model="scope.row[scope.column.property]" placeholder="请输入字符" />
<el-date-picker
v-if="item.type === '日期型'"
v-model="scope.row[scope.column.property]"
type="date"
placeholder="选择日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
/>
<!-- </el-input> -->
<el-input
v-if="item.type === '数值型'"
:id="'NumInput' + index + scope.$index"
v-model="scope.row[scope.column.property]"
placeholder="请输入数值"
oninput="value=value.replace(/[^\d]/g,'')"
@input="NumInput(index, scope.$index)"
/>
<el-select
v-if="item.type === '列表型'"
:ref="item.code + scope.$index"
v-model="tableData[scope.$index][item.code]"
:placeholder="item.index"
clearable
@visible-change="changeValueCategory($event, scope.$index, index)"
>
<el-option :value="tableData[scope.$index][item.code]" style="height: auto">
<el-tree
:ref="item.code +'Tree' + scope.$index"
:data="dynamicData[item.code]"
node-key="id"
:props="typeTreeProps"
@node-click="getTypeList(scope.$index, index)"
>
<span slot-scope="{ node }">{{ node.label }}</span>
</el-tree>
</el-option>
</el-select>
</template>
</el-table-column>
</el-table>
</el-row>
- :render-header="(h,obj) => addRedStar(h, obj, item.isWrited)" :动态列表涉及到动态判断是否是必填。借助此函数,在表头添加红色 * 号图标。
- id、ref、v-model : 都是动态拼接的,在列表中加入多条数据时,确保每个输入框或列表的某一项都是唯一值。
- scope.row :某一行的数据。
- scope.column :某一列的数据。
- scope.row[scope.column.property] : 当前项(单元格)的对应数据。
- οninput="value=value.replace(/[^\d]/g,'')" : 代码中这段表示只允许输入数字。
- header-cell-style : 可以为所有表头单元格设置一样的 Style。Element-ui中有介绍。
- empty-text : 空数据时显示的文本内容。Element-ui中有介绍。
数据来源要依据后端返回数据灵活变通,也可以和后端沟通想要的数据方式。
methods中:
- 数值类型时有触发检验,只允许输入正整数,必须绑定 id ,且 id 值为唯一值。
- 只有数值类型只允许输入数字的校验,与οninput="value=value.replace(/[^\d]/g,'')" 配合,也可以单独使用,但多条行数据或一条数据有多个数值校验时,多一个方法校验更有保障,只在HTML中校验有时候会失效,相同,只在方法中使用有时候也会失效。
// 数值型触发校验
NumInput(index, len) {
const num = index.toString() + len
const idName = 'NumInput' + num
var input = document.querySelector('#' + idName)
input.oninput = function() {
input.value = input.value.replace(/[^\d]/g, '')
}
},
有必填项时:
配合上面 :render-header="(h,obj) => addRedStar(h, obj, item.isWrited)" 的代码在methods中相结合:
用 item.isWrited 返回的数值进行判断是否是必填项
// 是否必填图标
addRedStar(h, { column }, required) {
if (required === '0') {
console.log('column', required)
return [
h('span', { style: 'color: red' }, '*'),
h('span', ' ' + column.label)
]
} else {
return [
// h('span', { style: 'color: red' }, '*'),
h('span', ' ' + column.label)
]
}
},
校验后的实现效果:
总结:
这一篇是刚发现问题的时候写了一部分,和之前写的VUE中显示范围有限,元素滚动时el-option超出元素显示范围,是一个模块的问题总结,如果有下拉框飞出问题,可以看看。现在工作没那么忙就赶快看看草稿箱里的文章,尽量都补充完成。