vue vxe-table :edit-config=“editConfig“ 可以编辑的表格

背景:

在vue中的表格有合并行、合并列的情况,可以使用插件vxe-table实现各种样式的表格。就是不能跨框架运行,只能运行在 vue 框架中。对于表格中的每一个单元格可以编辑,配置table表格可以编辑。行可编辑或者单元格可编辑。

  • 设置 edit-config={trigger: 'manual', mode: 'row'} 启用行编辑的功能

const editConfig = ref({ trigger: 'manual', mode: 'row' })

  • 通过 edit-config.trigger=click 设置单元格单击模式

const editConfig = ref({ trigger: 'click', mode: 'cell' })

  • 通过 edit-config.trigger=dblclick 设置单元格双击模式

const editConfig = ref({ trigger: 'dblclick', mode: 'cell' })

实现效果:

备注:单元格单击会触发表格的可编辑状态。:edit-render="{ name: 'VxeInput' }"编辑状态渲染的是input输入框,也可以写成下拉列表等表单组件。

核心代码:

表格绑定属性:edit-config

const editConfig = ref({ trigger: 'manual', mode: 'row' })

const editConfig = ref({ trigger: 'click', mode: 'cell' })

const editConfig = ref({ trigger: 'dblclick', mode: 'cell' })

javascript 复制代码
<div class="container1 infoState">
    <vxe-table :data="voyageCostState.tableData" empty-text="没有更多数据了!" :loading="voyageCostState.loading"
        :border="'full'" :align="'center'" :merge-cells="voyageCostState.mergeCells"
        :edit-config="voyageCostState.editConfig">
        <vxe-colgroup title="船舶信息" :header-cell-class-name="'header-cell'">
            <vxe-column v-for="(item, index) in voyageCostState.tableList" :field="item.prop" :title="item.label"
                :width="item.width" :key="index" :edit-render="{ name: 'VxeInput' }"></vxe-column>
        </vxe-colgroup>
    </vxe-table>
</div>

官网链接:点击跳转官网

官网代码:

javascript 复制代码
<template>
  <div>
    <vxe-table
      border
      show-overflow
      :edit-config="editConfig"
      :data="tableData">
      <vxe-column type="seq" width="70"></vxe-column>
      <vxe-column field="name" title="Name" :edit-render="{name: 'input'}"></vxe-column>
      <vxe-column field="sex" title="Sex" :edit-render="{name: 'input'}"></vxe-column>
      <vxe-column field="age" title="Age" :edit-render="{name: 'input'}"></vxe-column>
    </vxe-table>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const tableData = ref([
  { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
  { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
  { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
  { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' }
])
const editConfig = ref({
  trigger: 'click',
  mode: 'cell'
})

</script>

理论知识:

官网链接:点击跳转

理论知识总结:

trigger: "click",//触发方式 manual(手动触发方式,只能用于 mode=row),click(点击触发编辑),dblclick(双击触发编辑)

mode: 'cell',//编辑模式cell(单元格编辑模式),row(行编辑模式)

showIcon: true,//是否显示列头编辑图标

beforeEditMethod: ({ row, rowIndex, column, columnIndex }) => {

console.log('beforeEditMethod>>>', row, rowIndex, column, columnIndex);

const _point = [rowIndex, columnIndex];

return pointExists(voyageCostState.points, _point);

}//官方方法。用来自定义激活编辑之前逻辑,该方法的返回用来决定该单元格是否允许编辑

//自定义封装的方法,判断是否存在,存在返回true,否则返回false

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;

}

  • 触发方式分为三种:

manual(手动触发方式,只能用于 mode=row),

click(点击触发编辑),

dblclick(双击触发编辑)

  • 编辑模式分为两种:

cell(单元格编辑模式),

row(行编辑模式)

完整代码:

javascript 复制代码
<template>
    <div>
        <div class="container1 voyageCostState">
            <!-- 绑定:edit-config={}属性不生效 -->
            <vxe-table :data="voyageCostState.tableData" empty-text="没有更多数据了!" :loading="voyageCostState.loading"
                :border="'full'" :align="'center'" :merge-cells="voyageCostState.mergeCells"
                    :edit-config="voyageCostState.editConfig">
                <vxe-colgroup title="航次成本" :header-cell-class-name="'header-cell'">
                    <!-- 问题出在这儿,多级表头会不生效 -->
                    <template v-for="(item, index) in voyageCostState.tableList" :key="index">
                        <vxe-column :field="item.prop" :title="item.label" :width="item.width"
                            v-if="!item.children"></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"></vxe-column>
                        </vxe-colgroup>
                    </template>
                </vxe-colgroup>
            </vxe-table>
            <!-- 绑定:edit-config={}属性有效 -->
            <div class="container1 infoState">
                <vxe-table :data="voyageCostState.tableData" empty-text="没有更多数据了!" :loading="voyageCostState.loading"
                    :border="'full'" :align="'center'" :merge-cells="voyageCostState.mergeCells"
                    :edit-config="voyageCostState.editConfig">
                    <vxe-colgroup title="船舶信息" :header-cell-class-name="'header-cell'">
                        <vxe-column v-for="(item, index) in voyageCostState.tableList" :field="item.prop" :title="item.label"
                            :width="item.width" :key="index" :edit-render="{ name: 'VxeInput' }"></vxe-column>
                    </vxe-colgroup>
                </vxe-table>
            </div>
        </div>
    </div>
</template>

<script setup>
import { reactive, ref, watch } from "vue";

const voyageCostState = reactive({
    loading: false,
    isHeader: false,
    tableData: [
        {
            id: 10001,
            myType: '预算',
            actualQuantity: '请输入',
            cargoVolume: '请输入',
            freight: '请输入',
            actualQuantity: '请输入',
            actualQuantity: '请输入',
            actualQuantity: '请输入',
            fo_hcrh: '20',
            do_hcrh: '20',
            go_hcrh: '200',
        },
    ],
    tableList: [
        {
            label: "",
            prop: "myType",
            width: '10%',
        },
        {
            label: "燃油成本",
            prop: "actualQuantity",
            width: '30%',
            children: [
                {
                    label: "FO耗量",
                    prop: "fo_hcrh",
                    width: 180,
                },
                {
                    label: "DO耗量",
                    prop: "do_hcrh",
                    width: 180,
                },
                {
                    label: "GO耗量",
                    prop: "go_hcrh",
                    width: 180,
                },
                {
                    label: "燃油成本",
                    prop: "go_cost",
                    width: 180,
                },
            ]
        },
        {
            label: "其它收入",
            prop: "actualQuantity",
            width: '30%',
            children: [
                {
                    label: "装港",
                    prop: "loading_port",
                    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: "actualQuantity",
            width: '12.5%',
        },
    ],
    mergeCells: [],
    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: true,
        beforeEditMethod: ({ row, rowIndex, column, columnIndex }) => {
            console.log('beforeEditMethod>>>', row, rowIndex, column, columnIndex);
            const _point = [rowIndex, columnIndex];
            return pointExists(voyageCostState.points, _point);
        }
    },
})
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;
}
</script>

<style scoped>
:deep(.vxe-header--row) {
    background-color: #def0ff;

    &:last-child {
        background-color: #f5f9ff;
    }
}

.infoState {
    height: 400px;
}
</style>

写到这儿。。。发现有一个问题,多级表头无法触发可编辑状态。。。

示例代码:

示例一:没有多级表头

实现效果:

实现代码:

javascript 复制代码
<template>
    <div>
       <div class="container1 fuelConsumptionState">
                <vxe-table :data="fuelConsumptionState.tableData" empty-text="没有更多数据了!"
                    :loading="fuelConsumptionState.loading" :border="'full'" :align="'center'"
                    :merge-cells="fuelConsumptionState.mergeCells" :edit-config="fuelConsumptionState.editConfig">
                    <vxe-colgroup title="燃油耗量" :header-cell-class-name="'header-cell'">
                        <vxe-column v-for="(item, index) in fuelConsumptionState.tableList" :field="item.prop"
                            :title="item.label" :width="item.width" :key="index"
                            :edit-render="{ name: 'VxeInput' }"></vxe-column>
                    </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 fuelConsumptionState = reactive({
    loading: false,
    tableData: [
        {
            id: 10001,
            weikong: "预算",
            startOil: "Man",
            arrivalLoadingOil: "Man",
            pushOil: "Man",
            departureLoadingOil: "Man",
            arrivalDischargeOil: "Man",
            dischargeBunkering: "Man",
            departureDischargeOil: "Man",
        },
    ],
    tableList: [
        {
            label: "",
            prop: "weikong",
            width: "12.5%",
        },
        {
            label: "航次开始存油",
            prop: "startOil",
            width: "12.5%",
        },
        {
            label: "抵装港存油",
            prop: "arrivalLoadingOil",
            width: "12.5%",
        },
        {
            label: "加油量",
            prop: "pushOil",
            width: "12.5%",
        },
        {
            label: "离装港存油",
            prop: "departureLoadingOil",
            width: "12.5%",
        },
        {
            label: "抵卸港存油",
            prop: "arrivalDischargeOil",
            width: "12.5%",
        },
        {
            label: "加油量",
            prop: "dischargeBunkering",
            width: "12.5%",
        },
        {
            label: "离卸港存油",
            prop: "departureDischargeOil",
            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: true,
        beforeEditMethod: ({ row, rowIndex, column, columnIndex }) => {
            console.log('ajing>>>', row, rowIndex, column, columnIndex);
            const _point = [rowIndex, columnIndex];
            return pointExists(fuelConsumptionState.points, _point);
        }
    },
});
</script>

<style scoped>
:deep(.vxe-header--row) {
    background-color: #def0ff;

    &:last-child {
        background-color: #f5f9ff;
    }
}

.infoState {
    height: 400px;
}
</style>

示例二:没有多级表头,有合并表格

实现效果:

实现代码:

javascript 复制代码
<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>
</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);
        }
    },
});
</script>

<style scoped>
:deep(.vxe-header--row) {
    background-color: #def0ff;

    &:last-child {
        background-color: #f5f9ff;
    }
}

.infoState {
    height: 400px;
}
</style>

示例三:有多级表头

实现效果:

问题描述:

有多级表头的表格,配置属性就没有效果,具体原因还不知道。

二级表头有效,三级表头无效。

解决方式:

哈哈哈。。。真是粗心大意。。。好在解决了。。

相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax