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>

示例三:有多级表头

实现效果:

问题描述:

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

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

解决方式:

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

相关推荐
顾辰逸you2 分钟前
uniapp--咸虾米壁纸项目(一)
前端·微信小程序
方方洛16 分钟前
电子书阅读器:epub电子书文件的解析
前端·产品·电子书
idaibin17 分钟前
Rustzen Admin 前端简单权限系统设计与实现
前端·react.js
GISer_Jinger23 分钟前
Trae Solo模式生成一个旅行足迹App
前端·javascript
zhangbao90s24 分钟前
Intl API:浏览器原生国际化API入门指南
前端·javascript·html
艾小码26 分钟前
构建现代前端工程:Webpack/Vite/Rollup配置解析与最佳实践
前端·webpack·node.js
跟橙姐学代码31 分钟前
Python 集合:人生中最简单的真理,只有一次
前端·python·ipython
复苏季风32 分钟前
站在2025 年 来看,现在应该怎么入门CSS
前端·css
pepedd86434 分钟前
深度解剖 Vue3 架构:编译时 + 运行时的协作
前端·vue.js·trae
一枚前端小能手36 分钟前
🧪 改个代码就出Bug的恐惧,前端测试来帮忙
前端·测试