vue 原生table合并单元格多余数据问题?


 data_list:  [
            {
                question_code: "63",
                module_id: "20",
                module_name: "务效做例离场",
                sub_tool_code: "51",
                content_code: "97",
                question_type: 90,
                merge_number:1,
                item_attr: 42,
                item_attr_name: '普通题目',
                opr_date: "1982-10-09"
            },
             {
                question_code: "63",
                module_id: "20",
                module_name: "务效做例离场",
                sub_tool_code: "51",
                content_code: "97",
                question_type: 90,
                merge_number:1,
                item_attr: 42,
                item_attr_name: '普通题目2',
                opr_date: "1982-10-09"
            },
            {
                question_code: "63",
                module_id: "20",
                module_name: "务效做例离场",
                sub_tool_code: "51",
                content_code: "97",
                question_type: 90,
                merge_number:2,
                item_attr: 42,
                item_attr_name: '普通题目',
                opr_date: "1982-10-09"
            },
            {
                question_code: "63",
                module_id: "20",
                module_name: "务效做例离场",
                sub_tool_code: "51",
                content_code: "97",
                question_type: 90,
                merge_number:2,
                item_attr: 42,
                item_attr_name: '普通题目',
                opr_date: "1982-10-09"
            }
        ]

想要合并原生table单元格,merge_number大于2的代表需要合并,需要合并的内容为item_attr_name,但是合并后表格剩下的数据会像后移,应该如何隐藏掉多余的数据呢

实现这个需求,可以通过利用 Vue 指令来操作表格。以下是一个实现示例:

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>Module Name</th>
          <th>Item Attr Name</th>
          <th>Operation Date</th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="(row, rowIndex) in data"
          :key="rowIndex"
          v-bind:class="{ 'hidden-row': shouldHideRow(rowIndex) }"
        >
          <td v-if="!shouldHideCell(rowIndex, 0)" :rowspan="getRowSpan(rowIndex)">{{ row.question_code }}</td>
          <td v-if="!shouldHideCell(rowIndex, 1)" :rowspan="getRowSpan(rowIndex)">{{ row.module_name }}</td>
          <td>{{ row.item_attr_name }}</td>
          <td>{{ row.opr_date }}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: [
        {
          question_code: "63",
          module_id: "20",
          module_name: "务效做例离场",
          sub_tool_code: "51",
          content_code: "97",
          question_type: 90,
          merge_number: 1,
          item_attr: 42,
          item_attr_name: '普通题目',
          opr_date: "1982-10-09"
        },
        {
          question_code: "63",
          module_id: "20",
          module_name: "务效做例离场",
          sub_tool_code: "51",
          content_code: "97",
          question_type: 90,
          merge_number: 1,
          item_attr: 42,
          item_attr_name: '普通题目2',
          opr_date: "1982-10-09"
        },
        {
          question_code: "63",
          module_id: "20",
          module_name: "务效做例离场",
          sub_tool_code: "51",
          content_code: "97",
          question_type: 90,
          merge_number: 2,
          item_attr: 42,
          item_attr_name: '普通题目',
          opr_date: "1982-10-09"
        },
        {
          question_code: "63",
          module_id: "20",
          module_name: "务效做例离场",
          sub_tool_code: "51",
          content_code: "97",
          question_type: 90,
          merge_number: 2,
          item_attr: 42,
          item_attr_name: '普通题目',
          opr_date: "1982-10-09"
        }
      ]
    };
  },
  methods: {
    shouldHideRow(rowIndex) {
      // 判断该行是否需要隐藏
      return this.data[rowIndex]["merge_number"] > 1 && rowIndex % 2 === 0;
    },
    shouldHideCell(rowIndex, cellIndex) {
      // 根据前面隐藏的行数,判断该单元格是否需要隐藏
      let hiddenRowCount = 0;
      for (let i = 0; i < rowIndex; i++) {
        if (this.shouldHideRow(i)) {
          hiddenRowCount += 1;
        }
      }
      return (
        this.data[rowIndex]["merge_number"] > 1 &&
        (cellIndex === 0 || cellIndex === 1) &&
        rowIndex % 2 === 1 &&
        this.data[rowIndex - 1]["merge_number"] === 2 &&
        hiddenRowCount % 2 === 1
      );
    },
    getRowSpan(rowIndex) {
      // 合并单元格时,计算需要合并的行数
      if (this.shouldHideRow(rowIndex)) {
        return 0;
      }
      let rowSpan = this.data[rowIndex]["merge_number"];
      if (rowSpan > 1 && rowIndex % 2 === 1) {
        rowSpan += 1;
      }
      return rowSpan;
    }
  }
};
</script>

<style>
.hidden-row {
  display: none;
}
</style>

这个示例中,先在表格头部定义了表格的格式。在表格体中,使用 v-for 指令遍历数据列表,根据当前行的状态来动态绑定 class 属性,以隐藏多余的行数。

shouldHideRow(rowIndex) 方法用来判断当前行是否需要隐藏。当当前行需要合并,并且是偶数行时,返回 true,表示该行需要隐藏。在 v-bind:class 中根据该方法的返回值来绑定 hidden-row 类。

shouldHideCell(rowIndex, cellIndex) 方法用来判断该单元格是否需要隐藏。当单元格在第一列或第二列,并且是奇数行时,需要判断该行和上一行是否都需要隐藏。为了方便,这个方法中也判断了当前行是否需要隐藏,并且上一行的合并数量是 2,才会判断是否需要隐藏该单元格。

getRowSpan(rowIndex) 方法用来计算合并单元格时需要合并的行数。如果当前行需要隐藏,则返回 0。对于需要合并的行数,先根据 merge_number 属性计算得到,然后在奇数行时,需要额外添加一行来占用多余的单元格。在 v-bind:rowspan 中根据该方法的返回值绑定合并的行数。

最后,利用 CSS 的 .hidden-row 类来隐藏多余的行。

通过设置 rowSpan 和 colSpan 属性来合并单元格。对于数据列表,可以遍历整个列表,找到需要合并的单元格,然后设置相应的 rowSpan 或 colSpan 属性。
在合并单元格后,剩余数据会向后移动。要隐藏多余的数据,使用 CSS 中的 display: none; 属性将它们隐藏起来。
下面是示例代码,演示如何合并 table 单元格和隐藏多余的数据:

<table>
  <thead>
    <tr>
      <th>Question Code</th>
      <th>Module ID</th>
      <th>Module Name</th>
      <th>Sub Tool Code</th>
      <th>Content Code</th>
      <th>Question Type</th>
      <th>Item Attr</th>
      <th>Item Attr Name</th>
      <th>Date</th>
    </tr>
  </thead>
  <tbody>
    <!-- 遍历 data_list 列表 -->
    {% for item in data_list %}
      {% if item.merge_number > 1 %}
        <!-- 需要合并的单元格 -->
        <tr>
          <td rowspan="{{ item.merge_number }}">{{ item.question_code }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.module_id }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.module_name }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.sub_tool_code }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.content_code }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.question_type }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.item_attr }}</td>
          <td>{{ item.item_attr_name }}</td>
          <td rowspan="{{ item.merge_number }}">{{ item.opr_date }}</td>
        </tr>
        <!-- 隐藏多余的数据 -->
        {% for i in range(1, item.merge_number) %}
          <tr style="display: none;">
            <td>{{ item.question_code }}</td>
            <td>{{ item.module_id }}</td>
            <td>{{ item.module_name }}</td>
            <td>{{ item.sub_tool_code }}</td>
            <td>{{ item.content_code }}</td>
            <td>{{ item.question_type }}</td>
            <td>{{ item.item_attr }}</td>
            <td>{{ item.item_attr_name }}</td>
            <td>{{ item.opr_date }}</td>
          </tr>
        {% endfor %}
      {% else %}
        <!-- 不需要合并的单元格 -->
        <tr>
          <td>{{ item.question_code }}</td>
          <td>{{ item.module_id }}</td>
          <td>{{ item.module_name }}</td>
          <td>{{ item.sub_tool_code }}</td>
          <td>{{ item.content_code }}</td>
          <td>{{ item.question_type }}</td>
          <td>{{ item.item_attr }}</td>
          <td>{{ item.item_attr_name }}</td>
          <td>{{ item.opr_date }}</td>
        </tr>
      {% endif %}
    {% endfor %}
  </tbody>
</table>