El-table 懒加载表格中新增、删除遇到的问题

前言

我是用的版本是:
在这里插入图片描述
官方给的例子中只是一个单纯的展示,但实际需求中可能会有一些其他需求,比如新增、修改。
然后遇到了各种问题,因此记录一下。

记录

:tree-props="{ children: 'children', hasChildren: 'hasChildren' }",先说一下配置
从下图可以看到,懒加载方法只执行了一次。当你手动闭合再重新展开后并没有重新执行懒加载方法。
懒加载的判断是:

  • hasChildren为true,有小箭头,有小箭头才有加载的前提
  • 有加载前提后,再判断children有没有值,无值则执行

最开始时由于子级是没有数据的,因此展开时执行了懒加载;当子数据有值后,就不会再执行懒加载。

注意:这里是手动闭合再展开,而不是执行懒加载代码,这个后面会用到。
在这里插入图片描述

问题1

const loadTreeData = (row, treeNode, resolve) => {
    
    
    console.log('执行懒加载了');
    // setTimeout 相当于执行查询接口
    setTimeout(() => {
    
    
        const data = [
            {
    
    
                id: 2,
                date: '2023-07-02',
                name: 'no_2',
                address: '上海',
                children: [],
                hasChildren: false
            }
        ];
        // 添加父级节点,如果后台返回了父级id(父级id正确),不需要下面的操作
        data.forEach(item => {
    
    
            item.parentId = row.id;
        });
        // resolve 必须执行
        resolve(data);
        console.log('数据是:', row);
    }, 1000);
};

这是懒加载方法,正常懒加载执行完,页面上已经显示了子级数据,这时数据也已经变化了,但是确实这样的:可以看到children里面是空的
在这里插入图片描述
解决

 resolve(data);
 row.children = data;
 console.log('数据是:', row);

在这里插入图片描述
这个有什么作用呢?
1、比如说层级,需要递归计算吧,没有数据怎么计算。这里不能后端给,比如你删除了一个数据,层级需要重新计算更新。
2、后面新增时会用到。

问题2

新增的数据不显示,如果没有 row.children = data; 会出现下面的问题
新增了一条数据:1是页面上根本没有显示出来;2是children里的数据只有新增加的这条
在这里插入图片描述
解决

加上 row.children = data;
在这里插入图片描述

问题3

删除后,tableData里的数据已经删除了,但是页面未更新
在这里插入图片描述
这个比较难处理,你需要在删除后执行一下懒加载方法页面才会更新

定义一个map,将懒加载方法执行时的参数都保存起来

// 定义一个map
const lazyTreeData = new Map();

const loadTreeData = (tree, treeNode, resolve) => {
    
    
    console.log('执行懒加载了');
    // 保存参数
    lazyTreeData.set(row.id, [tree, treeNode, resolve]);
    // setTimeout 相当于执行查询接口
    setTimeout(() => {
    
    
        const data = [
            {
    
    
                id: 2,
                date: '2023-07-02',
                name: 'no_2',
                address: '上海',
                children: [],
                hasChildren: false
            }
        ];
        // 添加父级节点,如果后台返回了父级id(父级id正确),不需要下面的操作
        data.forEach(item => {
    
    
            item.parentId = row.id;
        });
        // resolve 必须执行
        resolve(data);
        row.children = data;
        console.log('数据是:', row);
    }, 1000);
};
const delChild = row => {
    
    
    // 查找父级节点
    const parent = findParent(tableData.value, row.parentId);
    if (parent) {
    
    
        parent.children = parent.children.filter(e => e.id !== row.id);
        console.log('删除后的数据:', tableData.value);
        // 刷新界面
        const [tree, treeNode, resolve] = lazyTreeData.get(row.id);
        loadTreeData(tree, treeNode, resolve);
    }
};

这里存在另一个问题,就是执行懒加载方法时什么时候查询接口,什么时候不查询

扫描二维码关注公众号,回复: 15610159 查看本文章
// 删除
const delChild = row => {
    
    
    // 查找父级节点
    const parent = findParent(tableData.value, row.parentId);
    if (parent) {
    
    
        parent.children = parent.children.filter(e => e.id !== row.id);
        console.log('删除后的数据:', tableData.value);
        // 刷新界面
        const [tree, treeNode, resolve] = lazyTreeData.get(parent.id);
        // 记录一下子数据
        newChildren.value = _.cloneDeep(parent.children);
        if (newChildren.value.length == 0) {
    
    
            // 如果用户想要全部删除,这时hasChildren设置为false就不会执行懒加载方法
            tableData.value[0].hasChildren = false;
            // 这里要注意,hasChildren = false时只是无箭头了。如果执行loadTreeData,还是会执行的
        } else {
    
    
            loadTreeData(tree, treeNode, resolve);
        }
    }
};

// 懒加载方法
const loadTreeData = (row, treeNode, resolve) => {
    
    
    console.log('执行懒加载了');
    // 保存参数
    lazyTreeData.set(row.id, [row, treeNode, resolve]);
    // setTimeout 相当于执行查询接口
    if (newChildren.value.length == 0) {
    
    
        // 正常的加载数据
        setTimeout(() => {
    
    
            const data = [
                {
    
    
                    id: 2,
                    date: '2023-07-02',
                    name: 'no_2',
                    address: '上海',
                    children: [],
                    hasChildren: false
                }
            ];
            // 添加父级节点,如果后台返回了父级id(父级id正确),不需要下面的操作
            data.forEach(item => {
    
    
                item.parentId = row.id;
            });
            // resolve 必须执行
            resolve(data);
            row.children = data;
            console.log('数据是:', row);
        }, 1000);
    } else {
    
    
        // 删除后执行的,用于刷新界面
        resolve(newChildren.value);
        row.children = newChildren.value;
        // 清空newChildren,避免影响其他层级的懒加载
        newChildren.value = [];
    }
};

完整代码及效果

效果
在这里插入图片描述
代码

<template>
    <div>
        <!-- 这里默认不展开全部,如果数据量多的话会有问题 -->
        <el-table :data="tableData" style="width: 100%" row-key="id" border lazy :default-expand-all="false"
            :load="loadTreeData" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
            <el-table-column prop="date" label="Date" />
            <el-table-column prop="name" label="Name" />
            <el-table-column prop="address" label="Address" />
            <el-table-column label="操作">
                <template #default="{ row, $index }">
                    <div>
                        <el-button type="primary" ="addChild(row)">新增</el-button>
                        <el-button type="primary" :disabled="$index == 0" ="delChild(row)">删除</el-button>
                    </div>
                </template>
            </el-table-column>
        </el-table>
    </div>
</template>

<script lang="ts" setup>
import {
    
     ref } from 'vue';
import _ from 'lodash';
const tableData = ref([
    {
    
    
        id: 1,
        date: '2023-07-01',
        name: 'no_1',
        address: '北京',
        children: [],
        hasChildren: true,
        parentId: -1
    }
]);
// 用于存储懒加载的入参
const lazyTreeData = new Map();
// 用于存储子级数据
const newChildren = ref([]);

// 懒加载方法
const loadTreeData = (row, treeNode, resolve) => {
    
    
    console.log('执行懒加载了');
    // 保存参数
    lazyTreeData.set(row.id, [row, treeNode, resolve]);
    // setTimeout 相当于执行查询接口
    if (newChildren.value.length == 0) {
    
    
        // 正常的加载数据
        setTimeout(() => {
    
    
            const data = [
                {
    
    
                    id: 2,
                    date: '2023-07-02',
                    name: 'no_2',
                    address: '上海',
                    children: [],
                    hasChildren: false
                }
            ];
            // 添加父级节点,如果后台返回了父级id(父级id正确),不需要下面的操作
            data.forEach(item => {
    
    
                item.parentId = row.id;
            });
            // resolve 必须执行
            resolve(data);
            row.children = data;
            console.log('数据是:', row);
        }, 1000);
    } else {
    
    
        // 删除后执行的,用于刷新界面
        resolve(newChildren.value);
        row.children = newChildren.value;
        // 清空newChildren,避免影响其他层级的懒加载
        newChildren.value = [];
    }
};

// 新增方法
const addChild = row => {
    
    
    let id = new Date().getTime();
    row.children.push({
    
    
        id: id,
        date: new Date().toLocaleString(),
        name: 'no_' + id,
        address: '北京',
        children: [],
        hasChildren: false,
        parentId: row.id
    });
    console.log('新增后的数据:', tableData.value);
};
// 删除
const delChild = row => {
    
    
    // 查找父级节点
    const parent = findParent(tableData.value, row.parentId);
    if (parent) {
    
    
        parent.children = parent.children.filter(e => e.id !== row.id);
        console.log('删除后的数据:', tableData.value);
        // 刷新界面
        const [tree, treeNode, resolve] = lazyTreeData.get(parent.id);
        // 记录一下子数据
        newChildren.value = _.cloneDeep(parent.children);
        if (newChildren.value.length == 0) {
    
    
            // 如果用户想要全部删除,这时hasChildren设置为false就不会执行懒加载方法
            tableData.value[0].hasChildren = false;
        } else {
    
    
            loadTreeData(tree, treeNode, resolve);
        }
    }
};

// 递归查找父级
const findParent = (tableData, parentId) => {
    
    
    for (let i = 0; i < tableData.length; i++) {
    
    
        if (tableData[i].id == parentId) {
    
    
            return tableData[i];
        } else {
    
    
            if (tableData[i].children) {
    
    
                return findParent(tableData[i].children, parentId);
            }
        }
    }
    return undefined;
};
</script>

<style lang="scss" scoped></style>

猜你喜欢

转载自blog.csdn.net/weixin_41897680/article/details/131556841