树形表格的渲染

首先通过函数模拟后端返回的数据

const getData_imitate = (): Promise<tableItem[]> => {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      resolve([
        { id: 1, name: "第一事业部", parentId: 0 },
        { id: 2, name: "第二事业部", parentId: 0 },
        { id: 3, name: "第三事业部", parentId: 0 },
        { id: 4, name: "第一研发部", parentId: 1 },
        { id: 5, name: "第一交付部", parentId: 1 },
        { id: 6, name: "第二研发部", parentId: 2 },
        { id: 7, name: "第二交付部", parentId: 2 },
        { id: 8, name: "第二运维部", parentId: 2 },
        { id: 9, name: "第二运维交付部", parentId: 8 },
        { id: 10, name: "第三研发部", parentId: 3 },
        { id: 11, name: "第三交付部", parentId: 3 },
      ]);
    }, 10);
  });
};

获取这个数据,并通过函数将这个扁平数组转化为树的形式 --文章最下方展示GetTreeData函数

const getList = async () => {
  list.value = await getData_imitate();
  //GetTreeData为造数函数
  tree.value = GetTreeData(list.value);
};

之后再来看template上的标签,data上绑定的数据是函数返回的树,这样一个属性的table就渲染出来了

    <ElTable
      :data="tree"
      row-key="id"
    >
      <ElTableColumn prop="name" label="部门名称"></ElTableColumn>
    </ElTable>

下面是树形表格展示的效果:

请添加图片描述

点击行实现展示子节点

方法一 通过eltable的toggleRowExpansion方法

使用这个方法要在原来eltable上额外加上ref,这样才能通过ref使用eltable的toggleRowExpansion方法

const tableRef = ref();
const onRowClick = (row, column) => {
	tableRef?.value?.toggleRowExpansion(row, row.expand);
};

方法二 通过expand-row-keys

在标签中这样写:需要注意的是 expand-row-keys需要搭配row-key属性才能生效,其次就是expand-row-keys中需要绑定一个数组

   <ElTable
      :data="tree"
      row-key="id"
      @row-click="onRowClick"
      ref="tableRef"
      :expand-row-keys="expandArr"
    >

expandArr中记录应该展开的行,通过onRowClick函数判断expandArr中的数据 --这里需要注意的是expandArr中存储的数据应该是字符串,我最开始在这里使用的数字就没有生效。之后就可以通过expandArr数组中的内容对应row-key确定哪些table行应该被展开了。

let expandArr = ref<string[]>([]);
const onRowClick = (row, column, event) => {
  if (expandArr.value.includes(String(row.id))) {
  	//expandArr中之前有这个数据 --去除它
    expandArr.value = expandArr.value.filter((item) => {
      return item != String(row.id);
    });
  } else {
  	//原来没有这个数据 --增加它
    expandArr.value.push(String(row.id));
  }
};

方法三 模拟元素点击

首先我们知道的是,在不做配置的table中,我们直接点击行是无法做到展开的,我们需要点击行前面像三角形一样的展开符;那如果我点击行的时候,通过代码获取展开符元素,在代码中模拟点击,就可以实现点击行的时候实现展开了。

ps:如果不是直接使用的树形数据传给data,而是使用懒加载形式创造的表格,那还是那上面两种方法都不能很好的生效使用,但这种方法可以在懒加载表格中使用

const onRowClick = (row, column, event) => {
  event?.currentTarget?.querySelector(".el-table__expand-icon")?.click();
};

附:GetTreeData函数

function GetTreeData(
  data,
  configName: { id: string; parentId: string; children: string } = {}
) {
  // 包含了id parentId children属性,可以对这些属性重命名
  configName = Object.assign(
    {},
    { id: "id", parentId: "parentId", children: "children" },
    configName
  );
  //如果传入的不是数组 或者 数组长度为零直接返回
  if (!(data instanceof Array) || data.length === 0) {
    return;
  }

  let arr = JSON.parse(JSON.stringify(data));
  let TreeData = [];
  let map = new Map(); //存在id,对应所在的内存地址
  let outputObj, pid;
  // 给map初始化一下
  arr.forEach((item) => {
    map.set(item[configName.id], item);
  });
  arr.forEach((item) => {
    if (map.has(item[configName.parentId])) {
      // 有父节点
      let parent = map.get(item[configName.parentId]);
      if (parent[configName.children]) {
        parent[configName.children].push(item);
      } else {
        parent[configName.children] = [item];
      }
    } else {
      // 无父结点,当作顶级节点
      TreeData.push(item);
    }
  });
  console.log(TreeData, "tree");
  return TreeData;
}
Logo

前往低代码交流专区

更多推荐