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

表格可编辑时,可能会波及到:

  1. 规定校验
    校验时,一个是保留按钮的校验,一个是底部提交按钮的校验
    下图这种,
  2. 数据联动

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>

上面这种表格的模式,须要做两局部的校验:

  1. 点击表格的保留按钮
  2. 点击底部的提交按钮

elemnt-ui的表单校验对这种嵌套表单校验不是很敌对,所以,不太倡议这种模式,或者手动弹窗提醒

开发

资料: vue、element-ui、form-create