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>
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- vue開發樹形結構組件(組件遞歸)
- vue遞歸實現樹形組件
- Vue使用el-tree 懶加載進行增刪改查功能的實現
- vue項目兩種方式實現豎向表格的思路分析
- Vue Element-ui實現樹形控件節點添加圖標詳解