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

1、演示

2、思路

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

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

html 复制代码
<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、全部代码

html 复制代码
<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、温馨提示

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

相关推荐
大橙子额3 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
WooaiJava1 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
爱喝白开水a2 小时前
前端AI自动化测试:brower-use调研让大模型帮你做网页交互与测试
前端·人工智能·大模型·prompt·交互·agent·rag
Never_Satisfied2 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
WeiXiao_Hyy2 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡3 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone3 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09013 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农3 小时前
Vue 2.3
前端·javascript·vue.js