vue + element实现可操作树形组件

树形结构的节点自定义: 序号+输入框+增删按钮 

功能实现:

  1. 单个节点的增加删除
  2. 多个节点批量的增加删除
  3. 保存生成新的树形数据
  4. ...

参考代码:

<template>
  <div>
    <!-- 按钮  -->
    <el-button type="primary" plain round @click="handlerCreate"
      >新建</el-button
    >
    <el-button type="primary" plain round @click="handlerDelete"
      >删除</el-button
    >
    <el-button type="primary" plain round @click="save">保存</el-button>
    <!-- 树形控件 -->
    <el-card>
      <el-tree
        ref="tree"
        class="tree"
        :data="treeData"
        node-key="id"
        :props="{ label: 'label', children: 'children' }"
        show-checkbox
        :expand-on-click-node="false"
        @check="selectRows"
        :default-expand-all="true"
      >
        <template v-slot="{ node, data }">
          <div>
            <!-- 每条数据的序号 -->
            <span class="index">{{
              `${
                getPosByIdInTree(treeData, data.id).length === 1
                  ? ++getPosByIdInTree(treeData, data.id)[0]
                  : ++getPosByIdInTree(treeData, data.id)[0] +
                    '.' +
                    ++getPosByIdInTree(treeData, data.id)[1]
              }`
            }}</span>
            <!-- 输入框 -->
            <el-input
              style="width: 500px"
              v-model="data.label"
              placeholder="请输入内容"
              clearable
            ></el-input>
            <!-- 单个删除 -->
            <el-button
              style="margin-left: 10px"
              type="success"
              plain
              circle
              icon="el-icon-minus"
              @click="handlerMinus(node, data)"
            ></el-button>
            <!-- 单个新增,二级节点隐藏新增按钮 -->
            <el-button
              v-if="data.parentId === null"
              type="success"
              plain
              circle
              icon="el-icon-plus"
              @click="handlerAdd(node, data)"
            ></el-button>
          </div>
        </template>
      </el-tree>
    </el-card>
  </div>
</template>

<script>
export default {
  data() {
    return {
      id: 1,
      treeData: [
        { label: '烛光照亮了晚餐', children: [], id: 1, parentId: null },
      ],
      selectionRows: [],
      halfCheckedNodes: [],
    }
  },
  methods: {
    // 保存
    save() {
      console.log(this.treeData) // 获取创建的树状结构
      const source = 3
      const pos = this.getPosByIdInTree(this.treeData, source)
      console.log(pos) //  不算根节点,测试通过
    },
    // 单个新增子节点
    handlerAdd(node, data) {
      console.log(node)
      const newChild = {
        id: ++this.id,
        label: '爱情转移',
        children: [],
        parentId: data.id,
      }
      if (!data.children) {
        this.$set(data, 'children', [])
      }
      data.children.push(newChild)
    },
    // 删除子节点节点
    handlerMinus(node, data) {
      const parent = node.parent
      const children = parent.data.children || parent.data
      const index = children.findIndex((d) => d.id === data.id)
      children.splice(index, 1)
    },
    // 新增一级节点
    handlerCreate() {
      this.treeData.push({
        label: '却照不出个答案',
        children: [],
        id: ++this.id,
        parentId: null,
      })
    },
    // 保存选择状态
    selectRows(data, arr) {
      console.log(data, arr)
      this.selectionRows = arr.checkedNodes
      console.log(arr.halfCheckedKeys)
      this.halfCheckedNodes = arr.halfCheckedNodes
    },
    // 批量删除节点
    handlerDelete() {
      if (this.selectionRows === []) return
      this.selectionRows.forEach((item) => {
        this.handlerMinus(this.$refs.tree.getNode(item), item)
      })
      this.halfCheckedNodes.forEach((item) => {
        this.$refs.tree.setChecked(item, false, true)
      })
    },

    // 获取每个节点的索引
    getPosByIdInTree(tree, id) {
      const tmp = [] // 路径数组
      const FindPos = (sourceTree, sourceId) => {
        sourceTree.forEach((item, index) => {
          if (item.id === sourceId) {
            tmp.push(index)
          } else {
            item.children.forEach((t, i) => {
              if (t.id === sourceId) {
                tmp.push(i)
                tmp.push(index)
              }
            })
          }
        })
      }
      FindPos(tree, id)
      return tmp.reverse()
    },
  },
}
</script>

<style lang="less" scope>
.el-tree-node__content {
  height: 50px !important;
}
.index {
  display: inline-block;
  background-color: #ddd;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 5px;
}
</style>

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值