vue使用拖拽方式创建结构树
程序员文章站
2022-04-06 21:01:02
本文实例为大家分享了vue使用拖拽方式创建结构树的具体代码,供大家参考,具体内容如下在页面中拖拽虚线框中的节点,创建向右的结构树,如下图记录实现思路:vuetree.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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。