当前位置: 首页 > article >正文

el-table的树形结构结合多选框使用,实现单选父子联动,全选,反选功能

<template>
  <div>
    <el-table
      :data="tableData"
      :row-key="rowKey"
      :default-expand-all="defaultExpandAll"
      :tree-props="treeProps"
    >
      <!-- 开启树形多选 -->
      <el-table-column v-if="showSelection" width="120" align="left">
        <template #header>
          <el-checkbox
            v-model="selectAll"
            :checked="selectAll"
            :indeterminate="isIndeterminate"
            @change="setCheckAll"
          />
          {{ selectionName }}
        </template>

        <template #default="scope">
          <el-checkbox
            v-model="scope.row[selectionConfig.checked]"
            :checked="scope.row[selectionConfig.checked]"
            :indeterminate="scope.row[selectionConfig.indeterminate]"
            :disabled="scope.row[selectionConfig.disabled]"
            @change="setCheck(scope.row)"
          />
        </template>
      </el-table-column>
      <el-table-column prop="name" label="Name" width="180" />
    </el-table>
  </div>
</template>

<script>
export default {
  props: {
    // 表格树形数据
    // 列配置项
    columnConfig: {
      type: Array,
      default: () => [
        {
          prop: 'default',
          label: '默认',
          width: '200',
          align: 'center',
          ownDefinedFn: () => {
            return '默认' // 可返回函数
          }
        }
      ]
    },
    // 数据唯一标识
    rowKey: {
      type: String,
      default: 'id'
    },
    // 默认展开所有节点
    defaultExpandAll: {
      type: Boolean,
      default: true
    },
    // 渲染嵌套数据的配置选项
    treeProps: {
      type: Object,
      default: () => ({
        children: 'children'
      })
    },
    // 默认开启树形多选框
    showSelection: {
      type: Boolean,
      default: true
    },
    // 树形多选框标题
    selectionName: {
      type: String,
      default: ''
    },
    // 多选框配置
    selectionConfig: {
      type: Object,
      default: () => ({
        checked: 'checked',
        indeterminate: 'indeterminate',
        disabled: 'disabled'
      })
    }
  },
  data() {
    return {
      selectAll: false, // 全选
      isIndeterminate: false, // 半选
      tableData: [
        {
          id: '1',
          name: '目录1',
          parentId: '0',
          checked: false,
          isItemIndeterminate: false,
          children: [
            {
              id: '1-1-1-1',
              name: '目录1-1-1-1',
              parentId: '1',
              checked: false,
              isItemIndeterminate: false,
              children: []
            },
            {
              id: '1-1-1-2',
              name: '目录1-1-1-2',
              parentId: '1',
              checked: false,
              isItemIndeterminate: false,
              children: []
            }
          ]
        },
        { id: '2', name: '目录2', parentId: '0', checked: false, children: [] },
        { id: '3', name: '目录3', parentId: '0', checked: false, children: [] },
        { id: '4', name: '目录4', parentId: '0', checked: false, children: [] }
      ]
    }
  },
  methods: {
    // 全选
    setCheckAll() {
      console.log(this.selectAll)
      this.tableData.forEach((item) => {
        if (!item[this.selectionConfig.disabled]) {
          item[this.selectionConfig.checked] = this.selectAll
        }
        this.setChildren(item, this.selectAll)
      })
      this.isIndeterminate = false
    },
    // 单选
    setCheck(row) {
      // 设置该单元格所有子节点状态
      this.setChildren(row, row[this.selectionConfig.checked])
      let result = this.setParentCheck(row)
      // 遍历到顶级,顶级无父节点,判断顶级节点是否都为选中
      if (!result) {
        let isAll = this.tableData.every((item) => {
          return item[this.selectionConfig.checked]
        })
        this.selectAll = isAll

        if (isAll) {
          this.isIndeterminate = false
        } else {
          let isIndeterminate = this.tableData.some((item) => {
            return item[this.selectionConfig.checked] || item[this.selectionConfig.indeterminate]
          })
          this.isIndeterminate = isIndeterminate
        }
      }
    },
    // 设置子节点
    setChildren(row, checked) {
      row[this.selectionConfig.indeterminate] = false

      if (row[this.treeProps.children]) {
        row[this.treeProps.children].forEach((item) => {
          if (!item[this.selectionConfig.disabled]) {
            item[this.selectionConfig.checked] = checked
            item[this.selectionConfig.indeterminate] = false

          }
          if (row[this.treeProps.children]) {
            this.setChildren(item, checked)
          }
        })
      }
    },
    // 设置父节点
    setParentCheck(row) {
      // 寻找该行数据的父节点
      let parent = null
      for (let i = 0; i < this.tableData.length; i++) {
        parent = this.findItem(this.tableData[i], row.parentId)
        if (parent != null) {
          break
        }
      }
      // 遍历该行的父节点下,所有的子节点
      if (parent != null) {
        if (parent[this.treeProps.children]) {
          // 子节点是否全都选中,如果是则则勾选该节点
          let isAll = parent[this.treeProps.children].every((item) => {
            return item[this.selectionConfig.checked]
          })
          parent[this.selectionConfig.checked] = isAll
          if (isAll) {
            parent[this.selectionConfig.indeterminate] = false
          } else {
            let isIndeterminate = parent[this.treeProps.children].some((item) => {
              return item[this.selectionConfig.checked]
            })
            parent[this.selectionConfig.indeterminate] = isIndeterminate
          }

          // 递归查找该行父级的父级节点
          this.setParentCheck(parent, parent[this.selectionConfig.checked])
        }
      } else {
        // 遍历到顶级,停止
        return null
      }
    },
    // 查递归找该行的父节点
    findItem(row, id) {
      if (row.id == id) {
        return row
      }
      if (row[this.treeProps.children]) {
        let parent = null
        for (let i = 0; i < row[this.treeProps.children].length; i++) {
          parent = this.findItem(row[this.treeProps.children][i], id)
          if (parent) {
            break
          }
        }
        return parent
      } else {
        return null
      }
    }
  }
}
</script>

<style lang="less" scoped></style>

参考链接

https://blog.csdn.net/weixin_47342392/article/details/139168459

人工智能学习网站

https://chat.xutongbao.top


http://www.kler.cn/news/312512.html

相关文章:

  • SpringBoot结合Mybatis-plus项目直接执行sql语句
  • Vue学习记录之五(组件/生命周期)
  • IO流体系(FiletOutputStream)
  • Go Testify学习与使用
  • Linux环境变量进程地址空间
  • 毕业设计选题:基于springboot+vue+uniapp的驾校报名小程序
  • MySQL从入门到精通二
  • Java企业面试题3
  • MySQL_图形管理工具简介、下载及安装(超详细)
  • 对ViT 中Patch Embedding理解
  • 用友U8二次开发工具KK-FULL-*****-EFWeb使用方法
  • Vue 依赖注入组件通信:provide / inject 使用详解
  • QUIC 和 HTTP/3:提升网络性能的关键技术
  • Spring Cloud Config 动态刷新原理分析
  • 视频单目标跟踪研究
  • 鸿蒙next web组件和h5 交互实战来了
  • 零基础到项目实战:Node.js版Selenium WebDriver教程
  • Gitee Pipeline 从入门到实战【详细步骤】
  • Spring Boot框架下校园信息管理平台的构建
  • Unborn安装CUDA Toolkit 12.2
  • android10 系统定制:增加应用使用数据埋点,应用使用时长统计
  • 2013-2023年专精特新小巨人企业财务指标数据
  • MySQL 数据库备份与恢复指南
  • 抖音下载别人作品怎么去掉水印
  • Spring Boot 集成 Redisson 实现消息队列
  • 【C#生态园】提升C#开发效率:深入了解自然语言处理库与工具
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • 探索未来智能:Moonshot AI 引领AI新纪元——M1超级模型
  • css百分比布局中height:100%不起作用
  • 牛客小白月赛101(栈、差分、调和级数、滑动窗口)