vue使用拖拽方式创建结构树

本文实例为大家分享了vue使用拖拽方式创建结构树的具体代码,供大家参考,具体内容如下

在页面中拖拽虚线框中的节点,创建向右的结构树,如下图

记录实现思路:

vueTree.vue

<template>

<div class="container">

<div class="node-container">

<div v-for="(item, index) in nodeList"

:key="index"

class="source-node"

draggable="true"

@dragstart="dragStart(item)">

{{ item }}

</div>

</div>

<div class="tree-container"

@dragover="allowDrop"

@drop="handleDrop">

<tree-node v-if="nodeData"

ref="node"

:nodeData="nodeData"

@delete-node="deleteTree" />

</div>

</div>

</template>

<script>

import TreeNode from './treeNode.vue'

import { Node } from './config.js'

export default {

name: 'vue-tree',

components: {

TreeNode

},

// 后代节点无法获取节点数据,即无法独立创建节点,所以将祖先节点的创建节点方法暴露给后代节点

provide () {

return {

createNode: this.createNode

}

},

data () {

return {

nodeList: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],

currNode: null,

nodeData: null

}

},

methods: {

// 开始拖拽,获取节点数据

dragStart (item) {

this.currNode = item

},

// 若未生成跟节点,则允许拖拽

allowDrop (event) {

if (!this.nodeData) {

event.preventDefault()

}

},

// 拖拽结束,生成节点

handleDrop () {

if (!this.nodeData) {

this.nodeData = this.createNode()

}

},

createNode () {

let node = new Node(this.currNode)

return node

},

// 根节点删除,删除整个树

deleteTree () {

this.nodeData = null

}

}

}

</script>

<style lang="scss" scoped>

.container {

padding: 20px;

width: calc(100% - 40px);

height: calc(100% - 40px);

.node-container {

height: 100px;

border: 1px dashed red;

display: flex;

.source-node {

width: 50px;

height: 30px;

background: #fff;

border: 1px solid blue;

text-align: center;

line-height: 30px;

margin: 10px;

cursor: pointer;

}

}

.tree-container {

height: calc(100% - 122px);

margin-top: 20px;

}

}

</style>

config,js

export class Node{

constructor(name){

this.name = name,

this.children = []

}

}

treeNode.vue

<template>

<!--

结构:最外层是node-inner,每个node-inner中有一个node与node-box,node存放当前节点,node-box存放当前节点的全部子节点,当前节点有几个子节点则node-box中就会有几个node-inner,以此循环

<node-inner>

<node></node>

<node-box>

<node-inner>

<node></node>

<node-box>...</node-box>

</node-inner>

<node-inner>

<node></node>

<node-box>...</node-box>

</node-inner>

...

</node-box>

</node-inner>

-->

<div class="node-inner">

<div class="node"

:class="{ 'drag-over-node': isDragover }"

@dragover="dragOver"

@dragleave="dragLeave"

@drop="nodeDrop">

<span class="name">{{nodeData.name}}</span>

<span class="del"

@click="deleteNode">删除</span>

</div>

<div v-show="nodeData.children.length > 0"

class="node-box">

<tree-node v-for="(item,index) in nodeData.children"

:key="index"

:nodeData="item"

@delete-node="deleteChild(index)" />

</div>

</div>

</template>

<script>

export default {

name: 'tree-node',

props: {

nodeData: {

type: Object,

default: () => { }

}

},

// 获取祖先节点传递的数据

inject: ['createNode'],

data () {

return {

isDragover: false

}

},

methods: {

// 节点允许拖拽添加子节点

dragOver (event) {

event.preventDefault()

if (!this.isDragover) {

this.isDragover = true

}

},

dragLeave () {

if (this.isDragover) {

this.isDragover = false

}

},

// 为节点添加子节点

nodeDrop () {

let node = this.createNode()

this.nodeData.children.push(node)

this.isDragover = false

},

// 删除当前节点,本质是交给父级删除子节点

deleteNode () {

this.$emit("delete-node")

},

// 接收删除子节点的指令并执行删除功能

deleteChild (index) {

this.nodeData.children.splice(index, 1)

}

}

}

</script>

<style lang="scss" scoped>

.node {

border: 1px solid orange;

border-radius: 4px;

position: relative;

display: inline-flex;

align-items: center;

justify-content: space-between;

background-color: #fff;

height: 36px;

padding: 0 12px 0 16px;

line-height: 36px;

margin-bottom: 10px;

.name {

font-size: 16px;

margin-right: 12px;

}

.del {

color: red;

font-size: 12px;

cursor: pointer;

}

&.drag-over-node {

box-shadow: 6px 6px 12px rgba(106, 20, 134, 0.15);

}

}

.node-box {

display: inline-flex;

flex-direction: column;

.node-inner {

margin-left: 80px;

// 连接竖条

&:not(:last-child):before {

position: absolute;

left: -70px;

top: 22px;

border: 1px solid orange;

content: "";

width: 8px;

background-color: #fff;

border-bottom-color: #fff;

height: 100%;

border-top-color: #fff;

z-index: 3;

}

// 连接横条

&:after {

left: -61px;

width: 60px;

content: "";

position: absolute;

top: 14px;

height: 8px;

border: 1px solid orange;

content: "";

background-color: #fff;

border-right-color: #fff;

border-left-color: #fff;

z-index: 3;

}

// 最后一个竖条圆滑拐角

&:nth-last-child(2):before {

border-bottom-left-radius: 6px;

border-bottom-color: orange;

}

// 第一个横条拉长

&:first-child:after {

left: -81px;

width: 80px;

z-index: 2;

}

}

}

.node-inner {

position: relative;

}

</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 vue使用拖拽方式创建结构树 的全部内容, 来源链接: utcz.com/p/239904.html

回到顶部