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>

Vue项目中使用Element UI实现两个树形组件(Tree)之间的跨树拖拽功能,主要依赖于Element UI提供的Tree组件的拖拽(drag-and-drop)功能。下面是基本的实现步骤和代码示例: 1. 引入Element UI的Tree组件,并确保在Vue项目中已经正确安装并使用了Element UI。 2. 在两个Tree组件中分别设置`draggable`属性为`true`,开启拖拽功能。 3. 设置每个Tree组件的`node-key`属性,为节点数据提供一个唯一的key值,这对于拖拽功能是必须的。 4. 为源Tree组件添加`allow-drag`属性,并为目标Tree组件添加`allow-drop`属性。这两个属性分别用于控制节点是否可以被拖拽和是否可以被放置。 5. 监听源Tree组件的`@node-drag-start`事件,获取被拖拽节点的数据。 6. 监听目标Tree组件的`@node-drop`事件,处理节点放置逻辑。 示例代码如下: ```vue <template> <div> <el-tree :data="data1" show-checkbox node-key="id" draggable :allow-drag="false" :allow-drop="true" @node-drop="handleDrop" > </el-tree> <el-tree :data="data2" show-checkbox node-key="id" draggable :allow-drag="true" :allow-drop="false" @node-drag-start="handleDragStart" > </el-tree> </div> </template> <script> export default { data() { return { data1: [ // Tree1的数据源 ], data2: [ // Tree2的数据源 ] }; }, methods: { handleDragStart(node, ev) { // 拖拽开始时的逻辑 console.log('开始拖拽节点:', node); }, handleDrop(params) { // 节点放置时的逻辑 const { dragNode, dropNode, dropPosition } = params; console.log('节点放置位置:', dropPosition); console.log('放置节点:', dropNode); console.log('拖拽节点:', dragNode); // 根据dropPosition更新数据源,实现节点的移动 } } }; </script> ``` 在`handleDrop`方法中,你需要根据`dropPosition`来决定节点移动的位置(例如,`'before'`、`'after'`、`'inner'`),并且更新你的数据源,以反映拖拽操作后的新结构。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值