后盾零碎,离不开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