javascript html表格中循环数据时如何多级合并行

czq61nw1  于 2023-03-21  发布在  Java
关注(0)|答案(3)|浏览(176)

我有像下面这样的数据与随机行数(三级),我想循环这个数据显示如下表
第一节第一节第一节第一节第一次
enter image description here

const myData = [
  {
    subject: "Math",
    class: [
      {
        name: "Math-01",
        results: [
          {student: "jame",score: "10"},
          {student: "kelvin",score: "4"},
          { student: "smith",score: "8"}
        ]
      },
      {
        name: "Math-02",
        results: [
          { student: "joe",score: "8"},
          {student: "yassou",score: "8"}
        ]
      }
    ]
  },
  {
    subject: "History",
    class: [
      {
        name: "History-01",
        results: [
          {student: "zoe", score: "6"},
          {student: "jame", score: "8"},
          {student: "bean", score: "9"}
        ]
      },
      {
        name: "History-02",
        results: [
          {student: "luffy", score: "10"},
        ]
      }
    ]
  },
  {
    subject: "literature",
    class: [
      {
        name: "literature-01",
        results: [
          {student: "nami", score: 5}
        ]
      },
      {
        name: "literature-02",
        results: [
          {student: "zoro", score: 3}
        ]
      },
      {
        name: "literature-03",
        results: [
          {student: "shank", score: 5}
        ]
      }
    ]
  }
]

我尝试了这种方法https://codesandbox.io/s/material-ui-table-demo-with-row-span-dq1w6,但它只适用于级别2
下面是我第2级代码,它可以工作

我继续将此逻辑应用于第3级,但它无法正常工作

任何人都可以帮助我用另一种方法,我希望表看起来像第一张图片从myData。
(*)注意:myData可以有更多的数据与不同的行数,所以我希望能够建立合并单元格表动态(但它仍然是相同的格式)
非常感谢。

lp0sw83n

lp0sw83n1#

const myData = [
  {
    subject: "Math",
    class: [
      {
        name: "Math-01",
        results: [
          {student: "jame",score: "10"},
          {student: "kelvin",score: "4"},
          { student: "smith",score: "8"}
        ]
      },
      {
        name: "Math-02",
        results: [
          { student: "joe",score: "8"},
          {student: "yassou",score: "8"}
        ]
      }
    ]
  },
  {
    subject: "History",
    class: [
      {
        name: "History-01",
        results: [
          {student: "zoe", score: "6"},
          {student: "jame", score: "8"},
          {student: "bean", score: "9"}
        ]
      },
      {
        name: "History-02",
        results: [
          {student: "luffy", score: "10"},
        ]
      }
    ]
  },
  {
    subject: "literature",
    class: [
      {
        name: "literature-01",
        results: [
          {student: "nami", score: 5}
        ]
      },
      {
        name: "literature-02",
        results: [
          {student: "zoro", score: 3}
        ]
      },
      {
        name: "literature-03",
        results: [
          {student: "shank", score: 5}
        ]
      }
    ]
  },
  {
    subject: "literature",
    class: [
      {
        name: "literature-01",
        results: []
      },
      {
        name: "literature-02",
        results: [ {student: "zoro", score: 3} ]
      },
      {
        name: "literature-03",
        results: [ {student: "shank", score: 5} ]
      }
    ]
  }
];

function App() {
  return (
    <table>
      {
        myData.map((record, i) => {
          let subjectHandled = false;
          return record.class.map((course, j) => {
            return course.results.map((r, k) => {
              let subjectTdEl;
              
              if (!subjectHandled && k === 0) {
                let resultsCount = 0;
                
                record.class.forEach((c) => {
                  resultsCount += c.results.length;
                });
                
                subjectTdEl = <td rowSpan={resultsCount}>{record.subject}</td>
                
                subjectHandled = true;
              }
              
              let courseTdEl;
              if (k === 0) {
                courseTdEl = <td rowSpan={course.results.length}>{course.name}</td>;
              }
              
              return (
                <tr key={k}>
                  {subjectTdEl}       
                  {courseTdEl}
                  <td>{r.student}</td>
                  <td>{r.score}</td>
                </tr>
              );
            });
          });
        })
      }
    </table>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
table {
  font-family: verdana;
  border-collapse: collapse;
}

table, th, td {
  padding: 10px;
  border: 1px solid black;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
gpnt7bae

gpnt7bae2#

我用javascript做了这个数据表。你可以检查和参考它。

function getData(){
    const myData = [
        {
            subject: "Math",
            class: [
                {
                    name: "Math-01",
                    results: [
                        {student: "jame",score: "10"},
                        {student: "kelvin",score: "4"},
                        {student: "smith",score: "8"}
                    ]
                },
                {
                    name: "Math-02",
                    results: [
                        {student: "joe",score: "8"},
                        {student: "yassou",score: "8"}
                    ]
                }
            ]
        },
            {
                subject: "History",
                class: [
                {
                    name: "History-01",
                    results: [
                        {student: "zoe", score: "6"},
                        {student: "jame", score: "8"},
                        {student: "bean", score: "9"}
                    ]
                },
                {
                    name: "History-02",
                    results: [
                        {student: "luffy", score: "10"},
                    ]
                }
            ]
        },
            {
                subject: "literature",
                class: [
                {
                    name: "literature-01",
                    results: [
                        {student: "nami", score: 5}
                    ]
                },
                    {
                    name: "literature-02",
                    results: [
                        {student: "zoro", score: 3}
                    ]
                },
                {
                    name: "literature-03",
                    results: [
                        {student: "shank", score: 5}
                    ]
                }
            ]
        }
    ];
    let html ="<table border='1|1'>";
    html +=`
    <tr> 
        <th>Subject</th>
        <th>Class</th>
        <th>Student</th>
        <th>Score</th> 
    </tr>`;
    myData.forEach((item) => {
        let subject = item.subject;
        let row = subject == 'Math' ? 5 : subject == 'History' ? 4 : 3;
        html += `<th rowspan="${row}"> ${subject} </th>`;
        item.class.forEach((item2) => {
            html += `<th rowspan="${item2.results.length}">${item2.name}</th>`;
            item2.results.forEach((item3 => {
                let name = item3.student;
                let score = item3.score;
                html += `<td>${name}</td><td>${score}</td></tr>`;
            }))
        })
    })
    html += "</table>";
    document.body.innerHTML = html;
}
<body onLoad="getData()">
kqlmhetl

kqlmhetl3#

我在reactjs方面没有经验,但我可以给予你一些建议,告诉你如何构建数据库来有效地处理这个问题。我过去用另一个处理树数据的Javascript框架做过这个。
您正在对数据集进行硬编码,每个级别都是不同的类型。这里的技巧是对数据集进行软编码以动态处理数据。因此,如果数据发生更改,则不必更改代码。如果您希望数据集真正具有动态性,我建议将数据模型更改为下面的模型。如果数据库无法更改,您可以编写一个视图,查询当前数据模型,使其看起来像新的数据模型。
创建一个名为node_hierarchy的表,其中包含parent_id、child_id和node_id。这些值是任意的,在将数据插入数据库时可以是任何唯一的值。此表的PK可以是parent_id和child_id的组合键。或者,您可以将concat_id作为PK,将它们串在一起,并使用单个列而不是两个列作为PK(复合)。还有一个名为node的表,其中包含node_id、node_type和node_value列。这样,您可以添加其他类型和多个级别,而无需担心更改源代码。每个表中的node_id成为关联,一个是node表中的FK,另一个是node_hierarchy表中的PK。
查询数据时,如果在树中重复某个节点,请确保节点的ID是parent_id + child_id的串联(hierarchy).意味着节点有多个父节点.如果节点没有多个父节点,忽略这一点.如果你没有串联id,你将在树中有重复的id,并可能在渲染时导致异常.通常情况下客户端树id需要唯一,因此使用reactjs进行验证。在构建数据集时,将concat_id添加到JSON数据中的节点,但在渲染时隐藏concat_id。仅用于参考。
查询数据时,您可以添加node_level,但也可以将其隐藏在渲染数据集中。该级别不应位于数据库中,因为它是基于具有唯一parent_id的node_hierarchy记录的数量动态变化的。如果与数据库中的数据集级别(node_level)不同,您甚至可以使用另一个render_level。
示例:

node_type, node_value [, concat_id, node_level, render_level]

----------------------- node_level = 0 ; render_level (ignored in query) ---------
root, Subject
root, Class
root, Student
root, Score
----------- node_level = 1 ; render_level (ignored in query) ------------
Subject, Math
Subject, History
Subject, Literature
------------------------ node_level = 2 ; render_level = 1 -------------
Class, Math-01
Class, Math-02
etc...
------------------- node_level = 3 ; render_level = 2 ------------
Student, Jame
Student, Calvin
etc...
------------------- node_level = 4 ; render_level = 3 --------------
Score, 10
Score, 4
etc...

在不知道你使用的数据库类型的情况下,我不能给予你任何代码来编写递归查询来拉取数据集。例如,如果你使用PostgreSQL,那么执行以下操作:
您对node_hierarchy的查询(或者node_tree,如果你这么叫的话),应该使用WITH RECURSIVE将祖先和后代联合到一个数据集中。node_level和render_level将是动态数据列值。使用INNER JOIN将节点表连接到node_hierarchy表(node.node_id = node_hierarchy.node_id)来获取静态数据列值。我使用单词“dynamic”和“static”的上下文是基于数据的检索。这允许您的静态数据(检索)在数据库中变得随着数据的存储/维护的上下文而动态。
JSON看起来像这样。要知道JSON在键/值对的值部分有变量,但插值后JSON的渲染HTML将不会(并且只会有值)。示例是this.nodes.node_value。这只是显示检索值的位置。一些JavaScript客户端框架允许JSON插值中的变量,有些则不允许。使用ReactJS进行验证。I'我这里不插入键。例如,name可以是this.parent_node.node_value(或者this.parent_node_value,如果它存在的话)。或者,例如,节点可以基于级别定义。所以节点将是级别2的“结果”。所以你可以在一些JS客户端框架中插入键或值。

const myData = [
  {
    concat_id: "0-1",
    parent_id: "0",
    child_id: "1",
    render_level: "1",
    subject: node_value <---- dynamically becomes "Math"
    nodes: [
    {
        concat_id: "1-2",
        parent_id: "1",
        child_id: "2",
        render_level: "2",
        name: node_value, < ---- dynamically becomes "Math-01"
        nodes: [
        {
            concat_id: "2-3",
            parent_id: "2",
            child_id: "3",
            render_level: "3",
            student: node_value, <---------- becomes "Jame"
            score: this.nodes.node_value <--------- becomes "10"
        },
        {
            concat_id: "2-4",
            parent_id: "2",
            child_id: "4",
            render_level: "3",
            student: node_value, <---------- becomes "Kelvin"
            score: this.nodes.node_value <--------- becomes "4"
        },
        {
            concat_id: "2-5",
            parent_id: "2",
            child_id: "5",
            render_level: "3",
            student: node_value, <---------- becomes "Smith"
            score: this.nodes.node_value <--------- becomes "8"
        }    
        ]
        }
    ]
]

实际上,node_type可以省略。node_type将有自己的节点。在我提供的数据集中,node_type将是父节点(祖先)的node_value,node_value将是子节点(后代)。
祝你好运我的朋友。

相关问题