kohaiy / easytable

A powerful data table based on vuejs. You can use it as data grid、Microsoft Excel or Google sheets. It supports virtual scroll、cell edit etc.
https://easytable.kohai.top/
19 stars 1 forks source link

点击表格header或左侧操作列后,再点击body区域,前端报错:Cannot read properties of null (reading 'includes') #3

Closed faylpf closed 3 months ago

faylpf commented 3 months ago

你好。我遇到了一个问题,不知道你这边是否有这个问题。 image 点击图片中的红色区域后,再点击绿色区域时,前端报错,报错信息如下: image 示例代码如下:

<template>
    <div class="app-container">
        <el-row :gutter="10" class="mb8">
            <el-col :span="1.5">
                <el-button
                        type="primary"
                        plain
                        icon="Plus"
                        size="large"
                        @click="handleAdd"
                >新增
                </el-button>
            </el-col>
        </el-row>
        <ve-table
                rowKeyFieldName="rowKey"
                :columns="columns"
                :table-data="tableData"
                borderY
                :cell-autofill-option="cellAutofillOption"
                :sort-option="sortOption"
                :columnHiddenOption="columnHiddenOption"
                :rowStyleOption="rowStyleOption"
                :column-width-resize-option="columnWidthResizeOption"
        />
        <!--
        :editOption="editOption"
        -->
    </div>
</template>
<script setup lang="tsx">
    import {ref} from 'vue'
    import '@easytable/vue/libs/theme-default/index.css';
    import {VeTable} from '@easytable/vue';
    import * as dayjs from "dayjs";
    const sortOption = ref({
        // sort always
        sortAlways: true,
        sortChange: (params) => {
            sortChange(params);
        },
    })
    const editOption = ref({
        beforeStartCellEditing: ({row, column, cellValue}) => {
            console.log("beforeStartCellEditing");
            console.log("row::", row);
            console.log("column::", column);
            console.log("cellValue::", cellValue);
            console.log("---");
            if (row.R === '已审核') {
                return false;
            }
        },
        beforeCellValueChange: ({row, column, changeValue}) => {
            console.log("beforeCellValueChange");
            console.log("row::", row);
            console.log("column::", column);
            console.log("changeValue::", changeValue);

            console.log("---");

            if (column.field === "number" && !/^\d+$/.test(changeValue)) {
                alert("请输入数字");
                return false;
            }
        },
        afterCellValueChange: ({row, column, changeValue}) => {
            console.log("afterCellValueChange");
            console.log("row::", row);
            console.log("column::", column);
            console.log("changeValue::", changeValue);
            console.log("---");
        },
    })
    const columnResizeInfo = ref({
        column: "",
        differWidth: "",
        columnWidth: "",
        tableWidth: "",
    })
    const columnWidthResizeOption = ref({
        // default false
        enable: true,
        // column resize min width
        minWidth: 30,
        // column size change
        sizeChange: ({column, differWidth, columnWidth}) => {
            columnResizeInfo.value.column = column;
            columnResizeInfo.value.differWidth = differWidth;
            columnResizeInfo.value.columnWidth = columnWidth;
        },
    })
    const rowStyleOption = ref({
        clickHighlight: true,
        hoverHighlight: true,
        stripe: true
    })
    const cellAutofillOption = ref(true)
    const columnHiddenOption = ref({
        // default hidden column keys
        defaultHiddenColumnKeys: ["id"],
    })
    const columns = [
        {
            field: "index",
            key: "index",
            operationColumn: true,
            title: "",
            width: 50,
            align: "center",
            renderBodyCell: ({row, column, rowIndex}, h) => {
                return ++rowIndex;
            },
            edit: false,
        },
        {key: "id", edit: false, title: "id", field: "id"},
        {key: "A", edit: false, title: "A", field: "A", fixed: "left" },
        {key: "B", edit: true, title: "B", field: "B", fixed: "left", sortBy: ""},
        {key: "C", edit: true, title: "C", field: "C", fixed: "left", sortBy: ""},
        {key: "D", edit: true, title: "D", field: "D", sortBy: ""},
        {key: "E", edit: true, title: "E", field: "E", sortBy: ""},
        {key: "F", edit: true, title: "F", field: "F", sortBy: ""},
        {key: "G", edit: true, title: "G", field: "G", sortBy: ""},
        {key: "H", edit: true, title: "H", field: "H", sortBy: ""},
        {key: "I", edit: true, title: "I", field: "I", sortBy: ""},
        {key: "J", edit: true, title: "J", field: "J", sortBy: ""},
        {key: "K", edit: true, title: "K", field: "K", sortBy: ""},
        {key: "L", edit: true, title: "L", field: "L", sortBy: ""},
        {key: "M", edit: true, title: "M", field: "M", sortBy: ""},
        {key: "N", edit: true, title: "N", field: "N", sortBy: ""},
        {key: "O", edit: true, title: "O", field: "O", sortBy: ""},
        {key: "P", edit: true, title: "P", field: "P", sortBy: ""},
        {key: "Q", edit: true, title: "Q", field: "Q", sortBy: ""},
        {key: "R", edit: false, title: "R", field: "R", sortBy: ""},
        {
            field: "",
            key: "e",
            title: "S",
            width: "",
            center: "left",
            fixed: "right",
            renderBodyCell: ({ row, column, rowIndex }, h) => {
                return(
                    <span>
                        <el-button
                            class="button-demo"
                            onClick={() => deleteRow(rowIndex)}
                        >
                                        删除
                                    </el-button>
                                </span>
                );
            },
        }]
    const tableData = ref([])
    const cjtimeOptions = ref(['4:00', '8:00', '10:00', '12:30', '14:00', '16:30', '17:30'])
    const maxRowKey = ref(0);
    initTableData()
    function initTableData() {
        let data = [];
        let length = 10, min = 0, max = 100;
        for (let i = 0; i < length; i++) {
            data.push({
                rowKey: i,
                id: Math.floor(Math.random() * length) + 1,
                A: `a`,
                B: dayjs(new Date()).format("YYYY-MM-DD"),
                C: getRandomCjtime(),
                D: (Math.random() * (max - min) + min).toFixed(2),
                E: (Math.random() * (max - min) + min).toFixed(2),
                F: (Math.random() * (max - min) + min).toFixed(2),
                G: (Math.random() * (max - min) + min).toFixed(2),
                H: (Math.random() * (max - min) + min).toFixed(2),
                I: (Math.random() * (max - min) + min).toFixed(2),
                J: (Math.random() * (max - min) + min).toFixed(2),
                K: (Math.random() * (max - min) + min).toFixed(2),
                L: (Math.random() * (max - min) + min).toFixed(2),
                M: (Math.random() * (max - min) + min).toFixed(2),
                N: (Math.random() * (max - min) + min).toFixed(2),
                O: (Math.random() * (max - min) + min).toFixed(2),
                P: (Math.random() * (max - min) + min).toFixed(2),
                Q: (Math.random() * (max - min) + min).toFixed(2),
                R: Math.random() >= 0.5 ? '已审核' : '未审核'
            });
            maxRowKey.value = i;
        }
        tableData.value = data;
    }

    function getRandomCjtime() {
        const randomIndex = Math.floor(Math.random() * cjtimeOptions.value.length);
        return cjtimeOptions.value[randomIndex]
    }

    function handleAdd() {
        addNewItem()
    }

    function addNewItem() {
        const newObject = columns.reduce((obj, {field}) => {
            if (field === "A") {
                obj[field] = "a"
            } else if (field === "B") {
                obj[field] = dayjs(new Date()).format("YYYY-MM-DD");
            } else if (field === "C") {
                const randomIndex = Math.floor(Math.random() * cjtimeOptions.value.length);
                obj[field] = cjtimeOptions.value[randomIndex]
            } else if (field === "id") {
                obj[field] = parseInt(Math.floor(Math.random() * 10000) + 1)
            } else if (field === "R") {
                obj[field] = '未审核';
            } else {
                if (field !== 'index') {
                    obj[field] = parseFloat((Math.random() * (0 - 0) + 0).toFixed(2)); // 假设值在0到100之间
                }
            }
            obj.rowKey = maxRowKey.value + 1;
            return obj;
        }, {});
        tableData.value.unshift(newObject);
        maxRowKey.value = maxRowKey.value + 1;
        console.log("tableData-->", tableData)
    }

    function deleteRow(rowIndex) {
        tableData.value.splice(rowIndex, 1);
    }

    function sortChange(params) {
        let prop = "";
        const json = JSON.parse(JSON.stringify(params))
        // 遍历键值对
        Object.entries(json).forEach(([key, value]) => {
            if (value != "") {
                prop = key;
            }
        });
        tableData.value.sort((a, b) => {
            if (params[prop] === "asc") {
                return a[prop] - b[prop];
            } else if (params[prop] === "desc") {
                return b[prop] - a[prop];
            } else {
                return 0;
            }
        });
    }
</script>
kohaiy commented 3 months ago

我本地试了下,怎么拖拽都没重现到,是有什么特殊的操作才会触发吗?

faylpf commented 3 months ago

我本地试了下,怎么拖拽都没重现到,是有什么特殊的操作才会触发吗?

不是拖拽。是点击表头或者操作列,然后再点击数据,会报错。如果你本地按照这个操作没有出现bug的话,那可能是我配置不对

kohaiy commented 3 months ago

我是有点来点去的,没重现到。 或者你可以在在线运行工具上跑下看看 https://codesandbox.io/

kohaiy commented 3 months ago

我创建了个在线运行的,也是没问题的,你可以看看 https://codesandbox.io/p/devbox/quizzical-agnesi-z896ny

faylpf commented 3 months ago

我创建了个在线运行的,也是没问题的,你可以看看 https://codesandbox.io/p/devbox/quizzical-agnesi-z896ny

非常感谢你的分享。老项目的配置有问题,后来在你分享的项目配置的基础上,添加上老项目的必须配置项,现在没问题了。