后台系统,离不开crud,而crud中,常常会有表格的身影。
表格可以直接、清晰地列出数据
背景
每天总是不断地复制粘贴,修修改改,没完没了的el-table>el-table-column...,不如整理成可配置可服用的组件~
基本表格
只需要展示信息
<template>
<el-table
:key="tableKey"
v-loading="tableConfig.isLoading"
:data="data"
v-bind="getTableAttrs(tableConfig)"
@sort-change="(data) => $emit('sort-change',data)"
@row-click="(...args) => handleAction('rowClick', args)"
>
<el-table-column
v-if="tableConfig.selection"
type="selection"
width="55"
/>
<template v-for="col in formateColumns">
<el-table-column
v-if="col.tableIsShow !== false && col.colProps && col.colProps.formatter"
:key="col.prop"
:label="col.label"
v-bind="col.colProps"
/>
<el-table-column
v-else-if="col.tableIsShow !== false && col.colProps && col.colProps.component"
:key="col.prop"
:label="col.label"
v-bind="col.colProps"
>
<template slot-scope="scope">
<component
:is="col.colProps.component"
:row="scope.row"
:index="scope.$index"
:column="col"
v-bind="col.colProps.props"
@action="(methodName, ...args) => handleAction(methodName,args)"
/>
</template>
</el-table-column>
<el-table-column
v-else-if="col.tableIsShow !== false"
:key="col.prop"
:label="col.label"
v-bind="col.colProps"
>
<template slot-scope="scope">
<span v-if="col.colProps && col.colProps.constant">
{{ col.colProps.constant[scope.row[col.prop]] }}
</span>
<span v-else>{{ scope.row[col.prop] }}</span>
</template>
</el-table-column>
</template>
<operation
v-if="tableConfig.operations"
:operations="getOperations(tableConfig)"
@action="(methodName, ...args) => handleAction(methodName, args)"
/>
</el-table>
</template>
<script>
import Operation from "./operation";
import ToolbarDropdown from "./toolbar-dropdown";
import { getPagination,getTableConfig} from "oa-ui/src/utils/fields-tools";
import {Table,TableColumn,Button} from "element-ui";
export default {
name: "OaTable",
components: {
Operation,
ToolbarDropdown,
ELTable:Table,
ElTableColumn:TableColumn,
ElButton:Button
},
props: {
size:{
type:String,
default: ''
},
tableConfig: {
type: Object,
default: function () {
return {
showHeader: true,
totalRecords: 0, // 总记录数
isLoading: false, // 是否loading状态
selection: false, // 是否多选
operations: {
btn: [
// 表格操作按钮
{ name: "编辑", method: "handleEdit" },
{ name: "删除", method: "handleDelete", needConfirm: true },
],
},
};
},
},
columns: {
type: Array,
default: function () {
return [];
},
},
data: {
// 数据
type: Array,
default: function () {
return [];
},
},
},
data() {
return {
tableKey: 0,
checkedColumnsName: null,
selectedSelection: this.defaultSelectedSelection || []
};
},
computed:{
tableSize(){
return this.size || this?.$ELEMENT?.size
},
formateColumns(){
return this.columns?.map(col=>{
return {
label: col.title,
prop: col.field,
...col
}
})
}
},
watch: {
checkedColumnsName(valArr) {
// 更新表格列数据
this.tableKey = this.tableKey + 1;
this.columns.forEach((item) => {
item.tableIsShow = valArr.indexOf(item.prop) >= 0;
});
},
},
created() {
// 初始化选中的列
const checkedColumns = [];
this.columns.forEach((item) => {
if (item.tableIsShow !== false) {
checkedColumns.push(item.prop);
}
});
this.checkedColumnsName = checkedColumns;
},
methods: {
getTableAttrs(tableConfig){
return {
size:this.tableSize,
border:true,
stripe:true,
fit:true,
highlightCurrentRow:true,
style:"width:100%",
...getTableConfig(tableConfig),
}
},
getPaginationAttrs(tableConfig){
return {
size:this.tableSize,
style:"text-align: right",
total:tableConfig.totalRecords,
...getPagination(tableConfig),
}
},
getOperations(tableConfig){
return {
size: this.tableSize,
...tableConfig.operations
}
},
handleAction(methodName,args){
this.$emit('action',methodName,...args)
}
},
};
</script>
开发的时候,关注在更多的业务上,而不是繁琐的写标签上
<oa-table
ref="dataTable"
:data="data"
:table-config="tableConfig"
:columns="columns"
@action="$_handleAction"
>
</oa-table>
<script>
export default {
data() {
return {
queryParam: {
// 搜索条件
_start: 0,
_length: 20,
_searching: {},
_order_field: undefined, // 排序配置
_order_type: undefined
},
data: [],
tableConfig: {
isLoading: false,
totalRecords: 0,
operations: false,
filterable: true
},
columns: [
{
field: "id",
title: "ID"
},
{
field: "name",
title: "名称",
type: "el-input",
config: {
showInSearch: false
},
value: "123"
},
{
field: "isValidText",
title: "是否启用",
config: {
showInTable: { sortable: false }
}
},
{
field: "showIndex",
title: "排序",
config: {}
},
{
field: "alias",
title: "更新时间",
config: {
showInTable: { sortable: false }
}
}
]
};
},
mounted() {
this.handleSearch(this.queryParam);
},
methods: {
handleSearch(param) {
const response = {
code: 20000,
data: {
dataList: [
{
id: "1",
groupId: "324",
code: null,
name: "测试name1",
alias: "2020-12-10 14:30:33",
itemLevel: null,
tag: null,
parentCode: null,
showIndex: 1,
isValid: 1,
isDisplay: null,
english: null,
isValidText: "是",
firstname: null,
secondname: null,
fisrtGroupId: null,
handlerName: null,
eId: null,
itemLevelText: "枚举值"
}
],
totalCount: 3,
other: null
},
message: "操作成功"
};
const { _searching, ...others } = param;
this.tableConfig.isLoading = true;
others.groupId = this.groupId;
setTimeout(() => {
this.data = response.data.dataList;
this.tableConfig.totalRecords = response.data.totalCount;
this.tableConfig.isLoading = false;
}, 2000);
},
handleInValid(row) {
alert("handleInValid");
},
$_handleAction(methodName, row) {
this[methodName] && this[methodName](row);
}
}
};
</script>
带搜索的表格
一般在最右边有操作按钮,编辑、删除、详情,点击弹窗、跳转、二次确认框
单元格可DIY
单元格里面的内容,需要处理,可能会显示几个信息
表格可编辑
表单嵌套表格,且表格可编辑
通过操作区域,触发单元格变为form组件
表格可编辑时,可能会涉及到:
- 规则校验
校验时,一个是保存按钮的校验,一个是底部提交按钮的校验
下图这种, - 数据联动
table组件的代码
<template>
<el-table
:key="tableKey"
:data="value"
border
size="small"
>
<template slot="empty">
<el-button
size="small"
@click="handleAdd"
>
新增
</el-button>
</template>
<template v-for="col in columns">
<el-table-column
:key="col.key"
:prop="col.prop"
v-bind="col"
>
<template slot-scope="{row,$index}">
<el-form-item
:prop="`${keyName}.${$index}.${col.prop}`"
:rules="col.rules"
>
<component
:is="col.type"
v-model="value[`${$index}`][`${col.prop}`]"
:row="row"
:index="$index"
:column="col"
v-bind="col.props"
/>
</el-form-item>
</template>
</el-table-column>
</template>
<el-table-column
label="操作"
align="center"
>
<template slot-scope="scope">
<el-button
v-if="scope.$index === value.length -1"
size="small"
type="text"
@click="handleAdd"
>
新增
</el-button>
<el-button
size="small"
type="text"
@click="handleDelete(scope)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
props:{
keyName:{
type:String,
required:true
},
value:{
type:Array,
default(){
return []
}
},
columns:{
type:Array,
default(){
return [{
label:"姓名",
prop:"name",
width:100,
type:'el-input',
align:'center',
rules:[{
required:true,message:'姓名不能为空'
}]
},{
label:"身高/cm",
prop:"height",
width:200,
type:'el-input-number',
align:'center',
props:{
placeholder:"请输入身高",
controlsPosition:'right'
},
rules:[{
required:true,message:'身高不能为空'
}]
},{
label:"爱好",
prop:"hobby",
width:200,
type:'el-input',
align:'center',
rules:[{
required:true,message:'爱好不能为空'
}]
}]
}
}
},
data(){
return {
tableKey:0
}
},
methods:{
handleDelete({$index}){
const v = this.value;
v.splice($index,1);
this.$set(this,'value',v)
},
handleAdd(){
this.value.push({
edit:true
});
}
}
}
</script>
下面这种表格的形式,需要做两部分的校验:
- 点击表格的保存按钮
- 点击底部的提交按钮
elemnt-ui的表单校验对这种嵌套表单校验不是很友好,所以,不太建议这种形式,或者手动弹窗提示
开发
材料: vue、element-ui、form-create
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。