vue element table多层级(树形)表格 新建同级 新建子级 删除

请添加图片描述
请添加图片描述
请添加图片描述

<template>
  <div>
    <div style="margin-bottom: 20px">
      <el-button
        v-if="tableData.length >= 1"
        type="primary"
        size="small"
        @click="sonTable"
        :loading="sonLoading"
      >
        新建子节点
      </el-button>
      <el-button
        v-if="tableData.length >= 1"
        type="primary"
        size="small"
        @click="peerTable"
        :loading="peerLoading"
      >
        新建同级节点
      </el-button>
      <el-button
        v-if="tableData.length < 1"
        type="primary"
        size="small"
        @click="reset(1)"
        :loading="newLoading"
      >
        新建节点
      </el-button>
      <el-button type="primary" size="small" @click="passData">
        确定
      </el-button>
    </div>
    <el-table
      v-loading="loading"
      :data="tableData"
      border
      row-key="key"
      style="width: 100%"
      default-expand-all
      :tree-props="{ children: 'childDto', hasChildren: 'hasChildren' }"
      @selection-change="handleSelectionChange"
    >
      <el-table-column
        type="selection"
        width="55"
        align="center"
        :selectable="selectAble"
      >
      </el-table-column>
      <el-table-column label="序号" align="center">
        <template slot-scope="scope">{{ scope.$index + 1 }}</template>
      </el-table-column>
      <el-table-column prop="branchName" label="名称" align="center">
        <template v-slot="scope">
          <span v-if="!scope.row.showInput">{{ scope.row.branchName }}</span>
          <i
            v-if="!scope.row.showInput"
            class="el-icon-edit icon"
            @click="showInput(scope.row)"
          ></i>
          <el-input
            v-focus
            v-if="scope.row.showInput"
            v-model="scope.row.branchName"
            @blur="inputBlur(scope.row)"
            placeholder="请输入内容"
          ></el-input>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" width="120">
        <template v-slot="scope">
          <el-button size="mini" type="text" @click="deleteTable(scope.row)"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "",
  components: {},
  props: {},
  data() {
    return {
      tableData: [],

      tableSelected: {},
      faTable: {},

      sonLoading: false,
      peerLoading: false,
      newLoading: false,
      loading: false,
      treeArr: [],
    };
  },
  filters: {},
  computed: {},
  watch: {},
  created() {},
  directives: {
    // 注册一个局部的自定义指令 v-focus
    focus: {
      // 指令的定义
      inserted(el) {
        // 聚焦元素
        if (el.querySelector("input")) {
          el.querySelector("input").focus();
        }
      },
    },
  },

  mounted() {
    // 1为新建 2为编辑 this.treeArr为编辑的数据
    this.reset(1);
  },
  beforeDestroy() {},
  methods: {
    // 新建 or 编辑
    reset(type) {
      this.tableData = [];
      this.newLoading = true;
      if (type === 1) {
        this.tableData = [
          {
            id: Math.random() + "",
            key: Math.random() + "",
            branchName: "",
            showInput: true,
          },
        ];
        this.tableData = this.flatten(this.tableData, 1);
      }
      if (type === 2) {
        if (this.treeArr.length > 0) {
          this.tableData = this.treeArr;
        } else {
          this.tableData = [
            {
              id: Math.random() + "",
              key: Math.random() + "",
              branchName: "",
              showInput: true,
            },
          ];
        }
        this.tableData = this.flatten(this.tableData, 2);
      }

      this.tableSelected = {};
      this.faTable = {};
      this.tableData.forEach((item) => {
        item.first = 1;
      });
      this.newLoading = false;
    },
    // 获取列表数据
    passData() {
      // 删除名称为空的数据
      this.tableData.forEach((item) => {
        if (item.branchName === "") {
          this.tableData = this.tableData.filter((items) => {
            return items.id !== item.id;
          });
        }
      });
      this.tableData = this.nullFlatten(this.tableData);
      
      // 最终数据+++++++++++++++++++++++++++++++++++
      console.log(this.tableData)

      this.$emit("passData", this.tableData);
    },
    // 删除名称为空的数据
    nullFlatten(arr) {
      arr.map((item) => {
        if (item.childDto !== undefined) {
          for (let i = 0; i < item.childDto.length; i++) {
            if (item.childDto[i].branchName === "") {
              item.childDto = item.childDto.filter((items) => {
                return items.id !== item.childDto[i].id;
              });
            }
          }
        }
        if (Array.isArray(item.childDto)) {
          this.nullFlatten(item.childDto);
        }
      });
      return arr;
    },
    // 名称不为空切失去焦点时隐藏input
    inputBlur(val) {
      if (val.branchName) {
        val.showInput = false;
      }
    },
    // 点击编辑名称
    showInput(val) {
      val.showInput = !val.showInput;
    },
    // 是否可选
    selectAble(row) {
      // 给数据手动添加一个新字段 status 默认为1, 如果需要设置disbaled; status 变为0
      if (row.status === 1) {
        return true;
      }
      return false;
    },
    // 选中方法
    handleSelectionChange(val) {
      if (val.length > 0) {
        this.tableSelected = val[0];
        this.tableData = this.flattenId(this.tableData, val[0].id);
        this.faTable = val[0];
      } else {
        this.tableSelected = {};
        this.faTable = {};
        this.tableData = this.flatten(this.tableData, 1);
      }
    },
    // 选中状态
    flatten(arr, type) {
      arr.map((item) => {
        this.$set(item, "status", 1);
        this.$set(item, "key", Math.random() + "");
        if (type === 1 && item.branchName === "") {
          this.$set(item, "showInput", true);
        } else {
          this.$set(item, "showInput", false);
        }
        if (Array.isArray(item.childDto)) {
          this.flatten(item.childDto, type);
        }
      });
      return arr;
    },
    // 修改选中其他状态
    flattenId(arr, id) {
      arr.map((item) => {
        if (item.id === id) {
          this.$set(item, "status", 1);
        } else {
          this.$set(item, "status", 0);
        }
        if (Array.isArray(item.childDto)) {
          this.flattenId(item.childDto, id);
        }
      });
      return arr;
    },
    // 新建子节点
    sonTable() {
      this.sonLoading = true;
      if (this.tableSelected.childDto === undefined) {
        let arr = [
          {
            id: Math.random() + "",
            key: Math.random() + "",
            parentId: this.tableSelected.id,
            branchName: "",
            showInput: true,
          },
        ];
        this.$set(this.tableSelected, "childDto", arr);
      } else {
        this.tableSelected.childDto.push({
          id: Math.random() + "",
          key: Math.random() + "",
          parentId: this.tableSelected.id,
          branchName: "",
          showInput: true,
        });
      }
      this.sonLoading = false;
    },
    // 新建同级节点
    peerTable() {
      this.peerLoading = true;
      let obj = {
        id: Math.random() + "",
        key: Math.random() + "",
        branchName: "",
        showInput: true,
        first: 1,
      };
      if (JSON.stringify(this.faTable) !== "{}") {
        if (this.faTable.first === 1) {
          this.tableData.forEach((item) => {
            if (item.status === 1) {
              this.tableData.push(obj);
            }
          });
        } else {
          this.tableData = this.sonFlatten(this.tableData, this.faTable.id);
        }
      }
      this.peerLoading = false;
    },
    // 子项新建同级节点
    sonFlatten(arr, id) {
      let obj = {
        id: Math.random() + "",
        key: Math.random() + "",
        parentId: this.faTable.id,
        branchName: "",
        showInput: true,
      };
      arr.map((item) => {
        if (item.childDto !== undefined) {
          for (let i = 0; i < item.childDto.length; i++) {
            if (item.childDto[i].id === id) {
              item.childDto.push(obj);
            }
          }
        }
        if (Array.isArray(item.childDto)) {
          this.sonFlatten(item.childDto, id);
        }
      });
      return arr;
    },
    // 删除
    deleteTable(val) {
      if (val.first === 1) {
        this.tableData = this.tableData.filter((item) => {
          return item.id !== val.id;
        });
      } else {
        this.tableData = this.delFlatten(this.tableData, val.id);
      }
    },
    // 子节点删除
    delFlatten(arr, id) {
      arr.map((item) => {
        if (item.childDto !== undefined) {
          for (let i = 0; i < item.childDto.length; i++) {
            if (item.childDto[i].id === id) {
              item.childDto = item.childDto.filter((items) => {
                return items.id !== id;
              });
            }
          }
        }
        if (Array.isArray(item.childDto)) {
          this.delFlatten(item.childDto, id);
        }
      });
      return arr;
    },
  },
};
</script>

<style scoped lang="scss">
::v-deep {
// 隐藏全选框
.el-table__header-wrapper .el-checkbox {
    display: none;
  }
}
// 编辑图标样式
.icon {
  color: #66b1ff;
  margin-left: 10px;
  cursor: pointer;
}
</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值