当前位置: 首页 > 知识库问答 >
问题:

element-ui - 基于vue2+element 实现左向右两个树形tree的跨树拖拽?

邹开畅
2024-07-29
<template>
    <div>
        <el-dialog title="编辑转换" :fullscreen="true" ref="dialog" :close-on-click-modal="false"
            :close-on-press-escape="false" :visible.sync="mappingDialog">
            <el-row>
                <el-col :span="10">
                    <el-tree :data="treeData1" ref="treeIn" class="tree" node-key="id" default-expand-all draggable
                        :props="defaultProps" :allow-drag="returnTrue" :render-content="renderTreeNode"
                        @node-drag-start="handleDragstart" @node-drag-end="handleInDragend"></el-tree>
                </el-col>
                <el-col :span="4">
                </el-col>
                <el-col :span="10">
                    <el-tree :data="treeData2" ref="treeOut" class="tree" node-key="id" default-expand-all draggable
                        :props="defaultProps" :allow-drop="returnTrue" :render-content="renderTreeNode"
                        @node-drag-end="handleOutDragEnd"
                                @node-drag-over="handleDragOver"
        @node-drag-leave="handleDragLeave"
                        @node-drop="handleDrop"></el-tree>
                        <!-- is-drop-inner -->
                </el-col>
            </el-row>
            <span slot="footer" class="dialog-footer">
                <el-button @click="handleClose()">取 消</el-button>
                <el-button class="new_btn_class" type="primary" @click="submit">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<script>
export default {
    name: 'schemaModal',
    data() {
        return {
            jsonData: '',
            mappingDialog: false,
            defaultProps: {
                children: 'children',
                label: 'label'
            },
            treeData1: [{
                id: 1,
                label: "一级",
                children: [{
                    id: 4,
                    label: "二级-1111",
                    isFile: true,
                }, {
                    id: 5,
                    label: "二级-2222",
                    isFile: true,
                }],
            }],
            treeData2: [{
                id: 2,
                label: "一级-2222",
                children: [{
                    id: 6,
                    label: "二级-3333",
                    isFile: true,
                },
                {
                    id: 7,
                    label: "二级-4444",
                    isFile: true,
                }],
            }],
        }
    },
    methods: {
        init(args) {
            this.mappingDialog = true;
            console.log(args, 123);
            this.treeData1 = [{
                id: 1,
                label: "一级",
                children: [{
                    id: 4,
                    label: "二级-1111",
                    isFile: true,
                }, {
                    id: 5,
                    label: "二级-2222",
                    isFile: true,
                }],
            }]
            this.treeData2= [{
                id: 2,
                label: "一级-2222",
                children: [{
                    id: 6,
                    label: "二级-3333",
                    isFile: true,
                },
                {
                    id: 7,
                    label: "二级-4444",
                    isFile: true,
                }],
            }]
        },
        handleClose() {
            this.mappingDialog = false;
        },
        submit() {
            console.log(this.treeData2)
        },
        renderTreeNode(h, { node, data, store }) {
            if (data.isFile) {
                return <span><i class="el-icon-document"></i> {data.label}</span>;
            } else {
                return <span><i class="el-icon-folder"></i> {data.label}</span>;
            }
        },
        //左侧节点触发拖拽
        handleDragstart(node, event) {
            console.log('start', node, event)
            //在左侧节点触发拖拽的时候触发右侧节点的拖拽事件
            this.$refs.treeOut.$emit('tree-node-drag-start', event, { node: node });
        },
        //拖拽结束,但是确定是否成功
        handleInDragend(draggingNode, endNode, position, event) {
            console.log('end', draggingNode, endNode, position, event)
            // 新的空节点
            let newData = { id: (+new Date), children: [] };
            //在左tree插入拖拽的节点
            this.$refs.treeIn.insertBefore(newData, draggingNode);
            //右tree触发结束拖拽事件
            this.$refs.treeOut.$emit('tree-node-drag-end', event);
            this.$nextTick(() => {
                // 如果是移动到了自身---
                console.log(this.$refs.treeIn.getNode(draggingNode.data))
                if (this.$refs.treeIn.getNode(draggingNode.data)) {
                    this.$refs.treeIn.remove(newData);
                    console.log('移动到自身')
                } else {
                    // 如果移动到了右tree上----
                    let data = JSON.parse(JSON.stringify(draggingNode.data));
                    this.$refs.treeIn.insertAfter(data, this.$refs.treeIn.getNode(newData));
                    this.$refs.treeIn.remove(newData);
                    console.log('移动到别的tree')
                }
            })
        },
        handleOutDragEnd(draggingNode, endNode, position, event) {
            // console.log('endOut', draggingNode, endNode, position, event)
        },
        handleDragOver({event}) {
            // 阻止默认事件,允许放置
            event.preventDefault();
        },
        handleDragLeave({event}) {
            // 清除放置效果
            event.preventDefault();
        },
        //结束拖拽,可得到拖拽来源与去向
        handleDrop(draggingNode, dropNode, dropType, ev) {
            // const dragNodeData = this.dragNode.data;
            // event.preventDefault();
            console.log('移动结束', draggingNode, dropNode, dropType);
        },
        returnTrue() {
            return true;
        },
        returnFalse() {
            return false;
        }
    }
}
</script>

页面显示图
image.png
想做成的页面显示图,只想知道二级-2222拖动到了二级-4444 并重新赋值
image.png

共有2个答案

蒋骏
2024-07-29

你找找这个vue2版本的 看看这个能不能适用https://sortablejs.github.io/Vue.Draggable/#/nested-example 这是他其中一个demo 有层级的

孟凯泽
2024-07-29

在Vue2和Element UI中实现两个树形控件(Tree)之间的跨树拖拽,主要涉及到监听拖拽事件并正确地在两个树之间移动节点。在你的代码中,你已经设置了一些基本的事件监听,但有几个地方需要调整以确保节点可以正确地从一个树移动到另一个树。

首先,我们需要确保拖拽的节点在handleDrop方法中能够正确地被添加到目标树中,并从源树中移除。此外,你的handleInDragend方法中的逻辑有些混乱,因为它试图在拖拽结束时插入一个空的节点,这在跨树拖拽的场景中并不适用。

以下是修改后的关键部分代码:

1. 移除handleInDragend中不必要的逻辑

因为拖拽结束时的逻辑将在handleDrop中处理,我们可以简化handleInDragend方法:

handleInDragend(draggingNode, endNode, position, event) {
    // 这里可以留空,或者添加一些清理工作
    console.log('Drag ended on source tree', draggingNode);
}

2. 完善handleDrop方法

handleDrop方法中,我们需要判断拖拽的节点是否来自另一个树,如果是,则将其添加到目标树,并从源树中移除。这里的关键是使用draggingNode.data来获取节点数据,并在两个树的数据结构中操作。

handleDrop(draggingNode, dropNode, dropType, ev) {
    ev.preventDefault(); // 阻止默认行为
    if (draggingNode.componentOptions.Ctor.options.name === 'ElTreeNode' && dropNode.componentOptions.Ctor.options.name === 'ElTreeNode') {
        // 跨树拖拽
        const sourceTree = draggingNode.context.$refs.treeIn === draggingNode.$el.closest('.el-tree') ? 'treeIn' : 'treeOut';
        const targetTree = dropNode.context.$refs.treeIn === dropNode.$el.closest('.el-tree') ? 'treeIn' : 'treeOut';

        if (sourceTree !== targetTree) {
            // 从源树中移除节点
            this.$refs[sourceTree].remove(this.$refs[sourceTree].getNode(draggingNode.data));
            // 将节点添加到目标树
            if (dropType === 'before' || dropType === 'after') {
                // 插入到兄弟节点之前或之后
                this.$refs[targetTree].insertBefore(draggingNode.data, this.$refs[targetTree].getNode(dropNode.data), dropType === 'after');
            } else if (dropType === 'inner') {
                // 插入为子节点
                if (!dropNode.data.children) {
                    dropNode.data.children = [];
                }
                dropNode.data.children.push(draggingNode.data);
            }
        }
    }
}

注意:这里的draggingNode.componentOptions.Ctor.options.name可能不是一个可靠的方式来判断节点是否来自Element UI的ElTreeNode组件,因为Vue组件的选项名(如name)可能会更改或不存在。一个更稳妥的方式是使用其他标识符或属性来判断节点来源。这里只是为了演示逻辑。

3. 确保draggableallow-drop属性正确设置

你已经设置了这些属性,但请确保它们在整个应用中保持一致和正确。

4. 调试和测试

在实际应用中,你可能需要添加更多的错误处理和调试语句来确保一切按预期工作。

通过上述修改,你应该能够实现从一个树到另一个树的跨树拖拽功能。

 类似资料:
  • 本文向大家介绍vue+element UI实现树形表格,包括了vue+element UI实现树形表格的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了vue+element UI实现树形表格的具体代码,供大家参考,具体内容如下 一、在component文件夹下新建如下treeTable文件夹,里面有2个文件: eval.js:将数据转换成树形数据 index.vue:树形表格组件 二

  • 如图所示,我需要在每一项的勾选框和文字的中间添加img图片,可自定义大小和左右间距,图片路径会同样返回在data数据中,请问该怎么做到呢? 参考文档地址:https://element.eleme.io/#/zh-CN/component/tree#fang-fa 在这里先谢谢各位解答的大哥大姐们,小弟感激不尽!!

  • 第一次获取数据不会回显,第二次才会回显 两个接口 第一个是获取所有的权限的,第二个是获取已有权限的 我第二次获取才会回显 搞一天了 也没找出来原因..... 主要代码:

  • 下拉的数据是动态加载的,有时候数据很多,想在下拉里加分页。

  • 本文向大家介绍Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input),包括了Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)的使用技巧和注意事项,需要的朋友参考一下 这篇博客主要介绍树形控件的两个小小的功能: 下拉菜单 输入过滤框 以CSS样式为主,也会涉及到Vue组件和element组件的使用。

  • 本文向大家介绍vue+element UI实现树形表格带复选框的示例代码,包括了vue+element UI实现树形表格带复选框的示例代码的使用技巧和注意事项,需要的朋友参考一下 一:在component文件夹下新建如下treeTable文件夹,里面有2个文件: eval.js:将数据转换成树形数据 index.vue:树形表格组件 二:在需要的地方引入该组件: 例如:在component文件夹下