前端开发攻略---合并表格单元格,表格内嵌套表格实现手风琴效果。

发布于:2024-04-26 ⋅ 阅读:(18) ⋅ 点赞:(0)

1、演示

2、思路

1、用传统的 <table></table> 表格标签来实现比较麻烦。因此通过模拟  表格标签 的写法用<div></div>来实现

2、表头和表格列数是相同的,因此可以确定代码结构

<div class="table">
    <div class="header">
      <div class="th"></div>
      <div class="th"></div>
      <div class="th"></div>
      <div class="th"></div>
      <div class="th"></div>
    </div>
    <div class="body">
      <div class="tr">
        <div class="td"></div>
        <div class="td"></div>
        <div class="td"></div>
        <div class="td"></div>
        <div class="td"></div>
      </div>
    </div>
  </div>

3、上述代码表示为一个一行五列的表格

4、通过flex进行布局

5、通过数组的长度来平分嵌套表格每一列的宽度/高度

3、全部代码

<template>
  <div class="table">
    <div class="header">
      <div class="th">Id</div>
      <div class="th">名字</div>
      <div class="th">年龄</div>
      <div class="th">朋友</div>
      <div class="th">性别</div>
    </div>
    <div class="body">
      <div class="tr" v-for="(item, index) in data">
        <div class="td">{{ item.id }}</div>
        <div class="td">{{ item.name }}</div>
        <div class="td">{{ item.age }}</div>
        <div class="td" style="flex-direction: column">
          <p @click="item.hide = !item.hide">展开详情</p>
          <div
            class="content"
            :style="{ height: item.hide ? '0px' : `${item.detail.length * 36}px` }"
            :class="item.hide ? '' : 'haveTopBorder'"
            :key="index"
          >
            <div class="content-row" v-for="item1 in item.detail">
              <div class="content-td" v-for="item2 in item1" :style="{ '--l': item1.length }">{{ item2 }}</div>
            </div>
          </div>
        </div>
        <div class="td">是</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'

const data = ref([
  {
    id: 1,
    name: '刘备',
    age: '18',
    detail: [
      ['1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111'],
    ],
    status: '男',
    hide: false,
  },
  {
    id: 2,
    name: '张飞',
    age: '50',
    detail: [
      ['1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '', '1111'],
      ['1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111', '1111'],
    ],
    status: '男',
    hide: false,
  },
  {
    id: 3,
    name: '关羽',
    age: '29',
    detail: [
      ['', '1111', '1111', '1111', '1111', '1111', '', '1111', '1111', '', '1111'],
      ['1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111', '1111', ''],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
      ['1111', '', '1111', '1111', '', '1111', '1111', '1111', '1111', '1111', '1111'],
    ],
    status: '男',
    hide: false,
  },
])
</script>

<style scoped lang="scss">
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
.table {
  width: 1000px;
  border: 1px solid #eee;
  font-size: 14px;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: stretch;
    background-color: #b6bece;
    color: #3c3c3c;
    padding: 8px 0;
    .th {
      padding-left: 8px;
    }
  }
  .body {
    width: 100%;
    .tr {
      display: flex;
      width: 100%;
      justify-content: space-between;
      align-items: stretch;
      border-bottom: 1px solid #eee;
      .td {
        border-right: 1px solid #eee;
        padding: 8px 4px;
        display: flex;
        justify-content: flex-start;
        align-items: center;
      }
      .td:last-child {
        border-right: 0;
      }
    }
    .tr:last-child {
      border-bottom: 0;
    }
    p {
      width: 100%;
      display: flex;
      align-items: center;
      text-align: left;
      padding: 8px 0;
      cursor: pointer;
      user-select: none;
    }
  }
  .th,
  .td {
    text-align: left;
  }
  .th:nth-child(1),
  .td:nth-child(1) {
    width: 70px;
  }
  .th:nth-child(2),
  .td:nth-child(2) {
    width: 100px;
  }
  .th:nth-child(3),
  .td:nth-child(3) {
    width: 130px;
  }
  .th:nth-child(4),
  .td:nth-child(4) {
    flex: 1;
    padding: 0 !important;
  }
  .th:nth-child(5),
  .td:nth-child(5) {
    width: 70px;
  }
  .content {
    width: 100%;
    overflow: hidden;
    transition: height 0.2s;
    .content-row {
      display: flex;
      width: 100%;
      border-bottom: 1px solid #eee;
      .content-td {
        padding: 8px;
        width: calc(100% / var(--l));
        border-right: 1px solid #eee;
      }
      .content-td:last-child {
        border-right: 0;
      }
    }
    .content-row:last-child {
      border-bottom: 0;
    }
    .content-row:nth-child(even) {
      background-color: rgb(116, 182, 218);
    }
  }
  .haveTopBorder {
    border-top: 1px solid #eee;
  }
}
</style>

4、温馨提示

您可以找个干净的页面直接整个复制,根据您的需求更改即可