【vue】多级表格嵌套

1,663 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

本文以 elmentUI 的 el-table 表格为例实现以下需求:

  1. 当多级嵌套表格的表头不一致时
  2. 还要使用懒加载
  3. 在一行展开时重新发请求,关闭时不发

elment自带的方法将无法实现,本文就提供了解决的办法

效果展示

由演示图可以看到,点击一行展开时,只有当前行会出现loading效果,表示只有当前展开的这一行发请求了 表格嵌套.gif

完整代码

  1. 给一级el-table设置 row-key="id" 用于判断是当前点击行展开,发请求
  2. 给一级el-table设置 @expand-change="getNew" 行展开或者关闭时触发函数 getNew()
  3. 给一级el-table的第一列设置 type="expand<template v-slot="{row}"></template>包裹
  4. 给二级el-table设置 :data="row.children"v-loading="row.loading"
  5. getNew(row, expanded) 函数
  • row 代表当前展开或关闭行,是一个对象
  • expanded 代表当前所有展开行,是一个数组(里面是对象)
  • JSON.stringify(expanded).includes(JSON.stringify(row)) 判断当前行是否已经展开,为 true 代表点击将当前行展开;为 false 代表点击将当前行关闭
  • item.id === row.id 判断找到当前展开的行,把获取到的数据赋值进去
  1. 实现只有当前点击的展开行出现loading时,使用 this.$set( target , key , value)
  • target: 要更改的数据源(可以是一个对象或者数组)
  • key:要更改的具体数据 (索引)
  • value:重新赋的值
<template>
<div>
  <el-table
    :data="tableData"
    style="width: 100%;margin-bottom: 20px;"
    @expand-change="getNew"
    row-key="id"
  >
    <el-table-column type="expand">
      <template v-slot="{row}">
        <el-table
          border
          :data="row.children"
          v-loading="row.loading"
        >
          <el-table-column prop="date" label="时间" width="180" />
          <el-table-column prop="username" label="姓名" width="180" />
          <el-table-column prop="address" label="住址" width="180" />
        </el-table>
      </template>
    </el-table-column>
    <el-table-column prop="age" label="年龄" width="180" />
    <el-table-column prop="name" label="姓名" width="180" />
    <el-table-column prop="gender" label="性别" width="180" />
  </el-table>
</div>
</template>
<script>
  export default {
    data() {
      return {
        // 一级表格的数据
        tableData: [{
          id: "1",
          name: "张三",
          age: 18,
          gender: "男",
        },
        {
          id: "2",
          name: "李四",
          age: 19,
          gender: "男",
        },
        {
          id: "3",
          name: "王五",
          age: 20,
          gender: "男",
        },
        {
          id: "4",
          name: "男子",
          age: 21,
          gender: "男",
        }],
        // 模拟二级表格的数据,这里的数据再真实环境中是通过当前展开一级表格行的数据 发请求获得的
        children1: [
          {
            id: '5',
            address: '翻斗花园21号',
            date: "2016-05-01",
            username: "wangxiaohu",
          }
        ],
      }
    },
    methods: {
      getNew(row, expanded){
        console.log(row,expanded) // 当前行 当前已展开行
        // 判断让当前行展开
        if(JSON.stringify(expanded).includes(JSON.stringify(row)) === true){
          this.$set(row, 'loading', true)  // 表格加载开
          this.tableData.forEach(item => {
            // 找到当前展开的行,把获取到的数据赋值进去
            if(item.id === row.id) {
              console.log('id', item.id, row.id) // 可能打印四种 11 22 33 44
              item.children = this.children1 || []
            }
          })
          // 用定时器模拟发请求的延时过程
          setTimeout(() => {
            this.$set(row, 'loading', false) // 表格加载关
          }, 500)
        } else { // 让当前行关闭
          delete row.children // 删除当前关闭行的 children
          this.$set(row, 'loading', false) // 表格加载关
          delete row.loading // 删除当前关闭行的 loading
        }
      },
    },
  }
</script>

总结:以上的完整代码可以直接复制到 vue 文件中查看效果,此代码没有用接口和数据交互,只是给大家提供一个思路,有经验的开发人员自己去在真实项目中实现吧