这种效果要怎么做

数据如:嵌套级别不定

tableData: [
        {
          id: 1,
          projectName: '名称1',
          childList: [
            {
              id: 11,
              projectName: '名称11',
              childList: [
                {
                  id: 111,
                  projectName: '名称111'
                },{
                  id: 112,
                  projectName: '名称112'
                },
              ],
            },
          ],
        },
        {
          id: 2,
          projectName: '名称2',
          childList: [
            {
              id: 21,
              projectName: '名称21',
              childList: [
                {
                  id: 211,
                  projectName: '名称211'
                }
              ]
            }
          ]
        }
      ],

如何显示成下图的效果?

阅读 2.6k
4 个回答

1.先正常把表格渲染出来。
2.写一个合并单元格的代码。

我这边是让后端返回的每行数据里面增加了几个字段(合并了几行,几列),然后在定义表格数据的时候自定义渲染
image.png

基于 elementui 还好做一点。毕竟是 function 处理。

咱说说纯 vue + table 怎么实现吧。下面是个表格结构,合并的话是 rowspancolspan单词记错的话你自己找一下正确的

<table>
    <tr>
        <td></td><td></td><td></td>
    </tr>
    <tr>
        <td></td><td></td><td></td>
    </tr>
</table>

可以成要遍历所有叶子节点,然后输出叶子到根的路径。单纯依赖 v-for 的话不是很好写,需要判断只有index为1的时候才渲染并且放入合适的合并行,其他时期输出空白。

所以你可以直接在js中把树变成list,然后直接遍历即可,这样处理起来肯定比 v-for 要自由。

原生table实现:

遍历tableData,计算td的rowspan的值(遍历tableData item中的children)

// 遍历生成table

treeDataToTable(data) {
            var table = document.createElement("table");
            table.id = "myTable";
            table.border = 1;
            // 表头为项目名称和对应的个数,因此为两列
            let tr = document.createElement("tr");
            for (let i = 0; i < 2; i++) {
              let th = document.createElement("th");
              th.innerHTML = i == 0 ? "项目名称" : "次数";
              th.colSpan = i == 0 ? maxLevel : 1;
              tr.appendChild(th);
            }
            table.appendChild(tr);
            data.forEach((node, i) => {
              this.calTdOfRowspan(node, null, table);
            });
            return table;
          },

// 计算td对应的rowspan

calTdOfRowspan(node, tr, table) {
            let self = this;
            if (!tr) {
              tr = document.createElement("tr");
              table.appendChild(tr);
            }

            var rowSpan = 0;
            if (node.children && node.children.length) {
              var td = document.createElement("td");
              td.innerHTML = node.name;
              tr.appendChild(td);
              // 计算td对应的rowspan
              node.children.forEach(function (subNode, index) {
                let test = self.calTdOfRowspan(
                  subNode,
                  index === 0 ? tr : null,
                  table
                );
                rowSpan += test;
              });
              td.rowSpan = rowSpan;
            } else {
              for (let i = 0; i < 2; i++) {
                if (i == 0) {
                  // 表头第一列为项目名称
                  if (node.level < maxLevel) {
                    for (let i = 0; i <= maxLevel - node.level; i++) {
                      var td = document.createElement("td");
                      td.innerHTML = i == 0 ? node.name : "";
                      tr.appendChild(td);
                    }
                  } else {
                    var td = document.createElement("td");
                    td.innerHTML = node.name;
                    tr.appendChild(td);
                  }
                } else if (i == 1) {
                  // 表头第二列为次数
                  var td = document.createElement("td");
                  td.innerHTML = node.value || '';
                  tr.appendChild(td);
                }
              }
            }
            if (!rowSpan) {
              rowSpan = 1;
            }
            return rowSpan;
          },

// 获取树形数据的最深层级

          getMaxLevel(datas) {
            let max = 0;
            function eachData(data, level) {
              data &&
                data.forEach((item) => {
                  item.level = level;
                  if (level > max) {
                    max = level;
                  }

                  if (
                    item.hasOwnProperty("children") &&
                    item.children.length > 0
                  ) {
                    eachData(item.children, level + 1);
                  }
                });
            }
            eachData(datas, 1);
            return max;
          },
推荐问题