vue3可编辑表格
背景:
在vue3中可编辑表格,使用element组件实现效果不好,推荐使用插件。
这里封装了一个示例,包括二级表头、多级表头的封装。
实现效果:
完整代码:
<template><div><div class="container1 infoState"><vxe-table :data="infoState.tableData" empty-text="没有更多数据了!" :loading="infoState.loading" :border="'full'":align="'center'" :merge-cells="infoState.mergeCells" :edit-config="infoState.editConfig"><vxe-colgroup title="船舶信息" :header-cell-class-name="'header-cell'"><vxe-column v-for="(item, index) in infoState.tableList" :field="item.prop" :title="item.label":width="item.width" :key="index" :edit-render="{ name: 'VxeInput' }"></vxe-column></vxe-colgroup></vxe-table></div><div class="container1 incomeState"><vxe-table :data="incomeState.tableData" empty-text="没有更多数据了!" :loading="incomeState.loading":border="'full'" :align="'center'" :merge-cells="incomeState.mergeCells":edit-config="incomeState.editConfig"><vxe-colgroup title="航次收入" :header-cell-class-name="'header-cell'"><template v-for="(item, index) in incomeState.tableList" :key="index"><vxe-column :field="item.prop" :title="item.label" :width="item.width" v-if="!item.children":edit-render="{ name: 'VxeInput', placeholder: '请点击输入...' }"></vxe-column><vxe-colgroup v-else :title="item.label" :header-cell-class-name="'header-cell'"><vxe-column v-for="(item2, index2) in item.children" :field="item2.prop":title="item2.label" :width="item2.width" :key="index2":edit-render="{ name: 'VxeInput', placeholder: '请点击输入...' }"></vxe-column></vxe-colgroup></template></vxe-colgroup></vxe-table></div></div>
</template><script setup>
import { reactive, ref, watch } from "vue";
const pointExists = (points, target) => {for (let i = 0; i < points.length; i++) {if (points[i][0] === target[0] && points[i][1] === target[1]) {return true;}}return false;
}
const infoState = reactive({loading: false,tableData: [{id: 10001,name: "胜利号1168",cargoType: "",shipLook: "",shipTime: "",height: "",jHeight: "",length: "",width: "",xWidth: "",myType: "夏季吃水",draft: ""},{id: 10002,name: "航行方式",cargoType: "航速",shipLook: "航次日耗",shipTime: "航次日耗",height: "航次日耗",jHeight: "停泊日耗",length: "停泊日耗",width: "停泊日耗",xWidth: "31",myType: "热带吃水",draft: ""},{id: 10003,name: "航行方式",cargoType: "航速",shipLook: "FO(CST180)",shipTime: "DO(4#)",height: "GO(0#)",jHeight: "FO(CST180)",length: "DO(4#)",width: "GO(0#)",xWidth: "31",myType: "载重吨",draft: ""},{id: 10004,name: "设计航速",cargoType: "",shipLook: "",shipTime: "",height: "",jHeight: "",length: "",width: "",xWidth: "",myType: "散装舱容",draft: ""},{id: 10005,name: "经济航速",cargoType: "",shipLook: "",shipTime: "",height: "",jHeight: "",length: "",width: "",xWidth: "",myType: "TPC",draft: ""},],tableList: [{label: "船名",prop: "name",width: '10%',},{label: "航次",prop: "hangci",width: '12%',},{label: "船型",prop: "shipLook",width: '10%',},{label: "交船日期",prop: "shipTime",width: '10%',},{label: "总吨",prop: "height",width: '10%',},{label: "净吨",prop: "jHeight",width: '10%',},{label: "总长",prop: "length",width: '8%',},{label: "型宽",prop: "width",width: '8%',},{label: "其它信息",prop: "myType",width: '8%',},{label: "",prop: "draft",width: '14%',},],mergeCells: [{row: 1,col: 0,rowspan: 2,colspan: 1},{row: 1,col: 1,rowspan: 2,colspan: 1},{row: 1,col: 2,rowspan: 1,colspan: 3},{row: 1,col: 5,rowspan: 1,colspan: 3},],points: [[0, 0],[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 9],[1, 1], [1, 9],[2, 9],[3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 9],[4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [4, 7], [4, 9],],editConfig: {trigger: 'click',mode: 'cell',showIcon: false,beforeEditMethod: ({ row, rowIndex, column, columnIndex }) => {const _point = [rowIndex, columnIndex];return pointExists(infoState.points, _point);}},
});
const incomeState = reactive({loading: false,isHeader: false,tableData: [{id: 10001,weikong: "预算",actualQuantity: "",cargoVolume: "",freight: "",actualQuantity: "",actualQuantity: "",actualQuantity: "",fo_hcrh: "",do_hcrh: "",go_hcrh: "",total: ""},],tableList: [{label: "",prop: "weikong",width: "10%",},{label: "货量",prop: "cargoVolume",width: "10%",},{label: "运费",prop: "freight",width: "10%",},{label: "滞期费",prop: "actualQuantity",width: "30%",children: [{label: "装港停时",prop: "fo_hcrh",width: 180,},{label: "卸港停时",prop: "do_hcrh",width: 180,},{label: "滞期费",prop: "go_hcrh",width: 180,},],},{label: "其它收入",prop: "actualQuantity",width: "30%",children: [{label: "亏舱费",prop: "fo_hcrh",width: 180,},{label: "",prop: "do_hcrh",width: 180,},{label: "",prop: "go_hcrh",width: 180,},],},{label: "合计",prop: "total",width: "12.5%",},],points: [[0, 0],[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 9],[1, 9],[2, 9],[3, 0],[3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 9],],editConfig: {trigger: 'click',mode: 'cell',showIcon: false,beforeEditMethod: ({ row, rowIndex, column, columnIndex }) => {console.log('beforeEditMethod>>>', row, rowIndex, column, columnIndex);const _point = [rowIndex, columnIndex];return pointExists(incomeState.points, _point);}},
});
</script><style scoped>
:deep(.vxe-header--row) {background-color: #def0ff;&:last-child {background-color: #f5f9ff;}
}.infoState {height: 400px;
}.incomeState {height: 187px;
}
</style>
简单封装了一些。。。