el-table嵌套,实现父子选择框勾选联动(toggleRowSelection),并实现全选,单选,数据回显

效果图如下:

声明: 

代码参考与两位博主:

1.http://t.csdn.cn/5fuuyvue+element-ui 表格嵌套表格实现和勾选问题解决_vue表格嵌套表格_陈怂怂的博客-CSDN博客http://t.csdn.cn/5fuuy

2.【el-table嵌套父子勾选 并实现数据携带勾选的到另一张表中 】_el-tab表格勾选数据到另外一张表_️ht的博客-CSDN博客

感谢两位博主分享,不过有一些问题,例如单选,数据回显方面我做了详解和优化

在本文章中,我会讲一点代码的逻辑,仅供参考,因为代码是活的,人是死的

(如果人是活的,代码怎么可能是死的呢)

话不多说我们开始!


首先是el-table嵌套el-table

这里要注意两个地方

1. 主table
        1.1@select-all="mainSelectAll" -->主table的全选

        1.2@select="mainSelect" -->主table的单选

        1.3 :ref="main" -->主table的ref对象命名
2. 子table

        2.1@select="subSelect" -->子单选
        2.2@select-all="subSelectAll" -->子全选

        2.3 :ref="'sub' + scope.$index"  -->子table的ref对象命名(加上了下标)

<el-table v-loading="loading" :data="personList" @selection-change="handleSelectionChange" ref="main"
      @select-all="mainSelectAll" @select="mainSelect">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column type="expand">
        <template slot-scope="scope">
          <el-table :data="scope.row.attachmentList" border stripe size="small" :show-header="false"
            :ref="'sub' + scope.$index" @select="subSelect" @select-all="subSelectAll">
            <el-table-column type="selection" width="100" align="center" />
            <el-table-column prop="attachmentName" label="证件名称" width="350" show-overflow-tooltip>
              <template slot-scope="props">
                <span style="color:red">证件名称:</span>{{ props.row.attachmentName }}
              </template>
            </el-table-column>
            <el-table-column prop="attachmentTypeName" label="证件类型" width="350" show-overflow-tooltip>
              <template slot-scope="props">
                <span style="color:red">证件类型:</span>{{ props.row.attachmentTypeName }}
              </template>
            </el-table-column>
            <el-table-column prop="validityDate" label="证件到期时间" width="350" show-overflow-tooltip>
              <template slot-scope="props">
                <span style="color:red">证件到期时间:</span>{{ props.row.validityDate }}
              </template>
            </el-table-column>
            <el-table-column prop="updateTime" label="最后更新时间" width="350" show-overflow-tooltip>
              <template slot-scope="props">
                <span style="color:red">最后更新时间:</span>{{ props.row.updateTime }}
              </template>
            </el-table-column>
          </el-table>
        </template>
      </el-table-column>
 </el-table>

下面开始讲解各方法!!


在讲解各方法前,需要先理解三个东西!

1. toggleRowExpansion(row, expanded);

 这个方法是展开表格,当我选中主table的时候,自动将子table展开


2. clearSelection();

 用于取消全选,清空选择


3.toggleRowSelection(row, selected);

用于选中某条数据,row必须为单条数据(类似map形式),selected是否选中(true/false)


1. 主table的全选mainSelectAll方法

1. 取消全选时,循环main的数据拿到下标,将子table的所有全部选择都清空掉:clearSelection

2. 全选时将循环我personList(主表的数据),然后

        2.1:展开子table:toggleRowExpansion()方法

        2.2:如果selection有东西,执行主table选中/子table全选方法

        2.3:如果没有:执行cleanIs();清空方法

//主table全选
mainSelectAll(selection) {
  if (selection.length == 0) {
    var datas = this.$refs.main.data;
    datas.forEach((item, index) => {
      this.$refs[`sub${index}`].clearSelection()
    });
  } else {
    this.personList.forEach(async (item, index) => {
      await this.$refs['main'].toggleRowExpansion(item, true)
      if (selection.length !== 0) {
        let ls = new Array();
        ls.push(item);
        this.mainSelect(ls, item)
        this.subSelectAll(item.subList, index)
      } else {
        this.cleanIs(null, item)
      }
      this.$refs[`sub${index}`].clearSelection()
    });
  }
},

2. 主table的单选mainSelect方法

1. 参数讲解:

        1.1:selection->勾选过的数据

        1.2:row->当前点击勾选框的数据

2. 判断主table是否选中:isCheck

        2.1:查看selection是否存在row数据,如果没有就说明这条记录是取消

3. this.subIds

        subIds用于回显!!!!!!!!!!

//主table的单选
mainSelect(selection, row) {
  const isCheck = selection.includes(row);
  this.personList.forEach((item, index) => {
    if (item.id === row.id) {
      this.$refs.main.toggleRowExpansion(item, true);
      const tempList = row.attachmentList;
      this.$nextTick(() => {
        if (tempList.length !== 0) {
          tempList.forEach((childItem) => {
            this.selectAllChildMap.set(index, item);
            this.$refs.main.toggleRowSelection(item, isCheck);
            this.$refs[`sub${index}`].toggleRowSelection(childItem, isCheck);
            if (isCheck) {
              this.subIds.push(childItem.id);
            } else {
              this.subIds.pop(childItem.id);
            }
          })
        }
      })
    }
  })
  if (isCheck) {
    this.validIs(row.attachmentList);
  } else {
    this.cleanIs(null, row);
  }
},

3. 子table的全选subSelectAll()方法

1. 参数讲解

        1.1:selection -> 勾选过的数据

        1.2:clickIndex -> 下标(下标用于其他方法调用时,传进的参数)

//子表格勾选 --->联动一级表格
subSelectAll(selection, clickIndex) {
  if (selection != null && selection.length > 0) {
    const fatherRow = this.personList.find(item => {
      return item.id === selection[0].parentId
    })
    this.selectAllChildMap.set(clickIndex, fatherRow)
    this.$refs.main.toggleRowSelection(this.selectAllChildMap.get(clickIndex), true)
    // 非空时候 检验明细是否存在
    this.validIs(selection)
  } else {
    this.cleanIs(clickIndex, null);
    this.$refs.main.toggleRowSelection(this.selectAllChildMap.get(clickIndex), false)
    this.selectAllChildMap.delete(clickIndex)
  };
},

4. 子table的单选subSelect()方法

这里需要注意的是 我会循环selection 判断我本条数据是否存在,如果存在,flag为true;

1. 如果flag为true,则证明本条记录需要回显,会把id添加到全局变量的subIds里;

2. 如果flag为false,则需要把subIds里对应的记录删掉(本人不善于前端代码,所以用了最笨的方法就是循环重新赋值)

//子table单选
subSelect(selection, row) {
  const isCheck = selection.length > 0
  this.personList.forEach((item, index) => {
    if (item.id == row.tableId) {
      this.selectAllChildMap.set(index, item)
      this.$refs.main.toggleRowSelection(item, isCheck)
    }
  });
  let flag = false;
  selection.forEach((item, index) => {
    if (item.id == row.id) {
      //说明存在
      flag = true;
    }
  })

  if (flag) {
    this.subIds.push(row.id);
  } else {
    let ls = new Array();
    this.subIds.forEach(function(item, index, arr) {
      if (item == row.id) {

      } else {
        ls.push(item);
      }
    });
    this.subIds = ls;
  }
},

5. 其余代码(校验/清空/data里声明的参数 方面代码)

//data里需要声明的参数:
data() {
    return {
        selectAllChildMap: new Map(),
        ruleForm: {
            items: []
        },
}

---------------------------------------------------------------------------------
//一级勾选框和子级头部勾选框检验
validIs(selection) {
  // 非空时候 检验明细是否存在
  if (this.ruleForm.items.length === 0) {
    this.ruleForm.items.push(...selection)
  } else {

    let ids2 = this.ruleForm.items.map(f => f.id)
    selection.forEach(f => {
      if (ids2.indexOf(f.id) !== -1) {
        delete this.ruleForm.items[ids2.indexOf(f.id)]
      }
    })
    this.ruleForm.items = this.ruleForm.items.filter(f => f.id)
    ids2 = this.ruleForm.items.map(f => f.id)
    this.ruleForm.items.push(...selection)
  }
},

-----------------------------------------------------------------------------------------
//一级勾选框和子级头部勾选清空方法
cleanIs(clickIndex, fatherRow) {
  const childIdList = new Array();
  if (clickIndex != null && clickIndex >= 0) {
    childIdList.push(this.personList[clickIndex].attachmentList);
  } else {
    if (fatherRow != null && fatherRow != undefined) {
      childIdList.push(fatherRow.attachmentList);
    }
  }
  let ids2 = this.ruleForm.items.map(f => f.id)
  childIdList.forEach(f => {
    if (ids2.indexOf(f) !== -1) {
      delete this.ruleForm.items[ids2.indexOf(f)]
    }
  })
  this.ruleForm.items = this.ruleForm.items.filter(f => f.id)
  ids2 = this.ruleForm.items.map(f => f.id)
},

6. 数据结构

主table的personList就是这6条数据

每条数据内部有一个attachmentList:为我的子table的数据


7. 小结

1. 一定要理解最开始说的三个方法

        toggleRowExpansion

        clearSelection

        toggleRowSelection

2. 数据回显的subIds:一定是放在主/子table的单选方法里执行的,因为你全选时,会调用单选方法

3. 如果你看到这里,说明你还是仔细读了这篇文章,如果有什么问题,或者我有什么问题! 请随时提问指出!

谢谢大家!

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值