el-table树状结构自定义勾选列——只能勾选最末级子节点

186 阅读1分钟

目标需求:

  • 父节点禁止勾选,只能勾选最末级子节点
  • 支持切换单个最末级子节点
  • 全选或取消全选所有最末级节点

1.gif

<template>
  <div>
    <el-table
      ref="table"
      :data="tableData"
      row-key="id"
      border
      :indent="10"
      :select-on-indeterminate="true"
      @select="select"
      @select-all="selectAll"
      @selection-change="selectionChange"
      default-expand-all
      :tree-props="{ children: 'children' }"
    >
      <el-table-column
        type="selection"
        width="50"
        align="center"
        :selectable="selectable"
      >
        <template v-slot="scope">
          <!---自定义勾选列-从调试工具复制一份模板->
          <div class="cell">
            <label
              :class="{
                'el-checkbox': true,
                'is-checked': scope.row.isRowChecked,
                'is-disabled':
                  Array.isArray(scope.row.children) &&
                  scope.row.children.length > 0
              }"
            >
              <span
                :class="{
                  'el-checkbox__input': true,
                  'is-checked': scope.row.isRowChecked,
                  'is-disabled':
                    Array.isArray(scope.row.children) &&
                    scope.row.children.length > 0
                }"
              >
                <span class="el-checkbox__inner"> </span>
                <input
                  v-if="
                    Array.isArray(scope.row.children) &&
                      scope.row.children.length > 0
                  "
                  type="checkbox"
                  aria-hidden="false"
                  disabled
                  class="el-checkbox__original"
                  value=""
                />
                <input
                  v-else
                  type="checkbox"
                  aria-hidden="false"
                  class="el-checkbox__original"
                  value=""
                  @change="clickChildren(scope.row)"
                />
              </span>
            </label>
          </div>
        </template>
      </el-table-column>

      <el-table-column prop="name" label="姓名" sortable width="180">
      </el-table-column>
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column
        prop="date"
        label="日期"
        sortable
        width="180"
        show-overflow-tooltip
      >
      </el-table-column>
      <el-table-column prop="address" label="地址" show-overflow-tooltip>
      </el-table-column>
    </el-table>
    <p>{{ selectArr.map(el => el.id) }}</p>
    <div style="margin-top: 20px">
      <el-button @click="cancelAll()">取消选择</el-button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          id: 1,
          date: "2016-05-01",
          name: "1",
          address: "上海市普陀区金沙江路 1 弄",
          isRowChecked: false //每一个节点默认设置未勾选
        },
        {
          id: 2,
          date: "2016-05-02",
          name: "2",
          address: "上海市普陀区金沙江路 2 弄",
          children: null,
          isRowChecked: false
        },
        {
          id: 3,
          date: "2016-05-03",
          name: "3",
          address: "上海市普陀区金沙江路 2 弄",
          children: [
            {
              id: 31,
              date: "2016-05-31",
              name: "3-1",
              address: "上海市普陀区金沙江路 31 弄",
              children: []
            },
            {
              id: 32,
              date: "2016-05-32",
              name: "3-2",
              address: "上海市普陀区金沙江路 32 弄",
              children: [
                {
                  id: 321,
                  date: "2016-05-04",
                  name: "3-2-1",
                  address: "上海市普陀区金沙江路 321 弄"
                }
              ]
            }
          ]
        },
        {
          id: 4,
          date: "2016-05-04",
          name: "4",
          address: "上海市普陀区金沙江路 4 弄"
        }
      ],
      isAllCheck: false, // 全选/取消全选
      selectArr: [] // 勾选数组
    };
  },
  created() {
    this.initTableData(this.tableData);
  },
  methods: {
    //递归添加每个节点的勾选状态字段
    initTableData(parent) {
      parent.map(item => {
        this.$set(item, "isRowChecked", false);
        if (Array.isArray(item.children) && item.children.length > 0) {
          this.initTableData(item.children);
        }
      });
    },
    selectable(row) {
      // el-table 原生方法——设置禁止勾选,此时不起效
      // if (Array.isArray(row) && row.length > 0) {
      //   return false;
      // } else {
      //   return true;
      // }
      return true;
    },
    // 切换勾选单个末级节点
    clickChildren(row) {
      row.isRowChecked = !row.isRowChecked;
      this.toggleSelection(row, row.isRowChecked);
    },
    select(selection, row) {
      console.log("这种方法,@select监听不起效");
    },
    // 全选/取消全选
    selectAll() {
      this.isAllCheck = !this.isAllCheck;
      this.toggleSelectChildren(this.tableData, this.isAllCheck, "allCheck");
    },
    // 递归全选子节点
    toggleSelectChildren(parent, flag, operatorType) {
      if (operatorType == "allCheck") {
        parent.forEach(item => {
          this.toggleSelection(item, flag);
          if (Array.isArray(item.children) && item.children.length > 0) {
            this.toggleSelectChildren(item.children, flag, operatorType);
          }
        });
      }
    },
    // 可正常触发@selection-change监听
    selectionChange(selection) {
      this.selectArr = selection; // 包含父级和末级
      this.selectArr = this.selectArr.filter(
        item => !item.children || item.children.length < 1
      );
      console.log(this.selectArr);
    },
    // 切换单行的勾选状态
    toggleSelection(row, select) {
      if (row) {
        row.isRowChecked = select;
        this.$nextTick(() => {
          this.$refs.table && this.$refs.table.toggleRowSelection(row, select);
        });
      }
    },
    // 取消全选
    cancelAll() {
      // this.$refs.table.clearSelection(); el-table原生的清空,此时不起效
      this.toggleSelectChildren(this.tableData, false, "allCheck");
    }
  }
};
</script>

1.gif