共计 6563 个字符,预计需要花费 17 分钟才能阅读完成。
后盾零碎,离不开 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
正文完