vue使用拖拽方式創(chuàng)建結構樹
更新時間:2021年10月12日 10:03:48 作者:javscp_q
這篇文章主要為大家詳細介紹了vue使用拖拽方式創(chuàng)建結構樹,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
本文實例為大家分享了vue使用拖拽方式創(chuàng)建結構樹的具體代碼,供大家參考,具體內容如下
在頁面中拖拽虛線框中的節(jié)點,創(chuàng)建向右的結構樹,如下圖

記錄實現(xiàn)思路:
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
},
// 后代節(jié)點無法獲取節(jié)點數(shù)據(jù),即無法獨立創(chuàng)建節(jié)點,所以將祖先節(jié)點的創(chuàng)建節(jié)點方法暴露給后代節(jié)點
provide () {
return {
createNode: this.createNode
}
},
data () {
return {
nodeList: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
currNode: null,
nodeData: null
}
},
methods: {
// 開始拖拽,獲取節(jié)點數(shù)據(jù)
dragStart (item) {
this.currNode = item
},
// 若未生成跟節(jié)點,則允許拖拽
allowDrop (event) {
if (!this.nodeData) {
event.preventDefault()
}
},
// 拖拽結束,生成節(jié)點
handleDrop () {
if (!this.nodeData) {
this.nodeData = this.createNode()
}
},
createNode () {
let node = new Node(this.currNode)
return node
},
// 根節(jié)點刪除,刪除整個樹
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存放當前節(jié)點,node-box存放當前節(jié)點的全部子節(jié)點,當前節(jié)點有幾個子節(jié)點則node-box中就會有幾個node-inner,以此循環(huán)
<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: () => { }
}
},
// 獲取祖先節(jié)點傳遞的數(shù)據(jù)
inject: ['createNode'],
data () {
return {
isDragover: false
}
},
methods: {
// 節(jié)點允許拖拽添加子節(jié)點
dragOver (event) {
event.preventDefault()
if (!this.isDragover) {
this.isDragover = true
}
},
dragLeave () {
if (this.isDragover) {
this.isDragover = false
}
},
// 為節(jié)點添加子節(jié)點
nodeDrop () {
let node = this.createNode()
this.nodeData.children.push(node)
this.isDragover = false
},
// 刪除當前節(jié)點,本質是交給父級刪除子節(jié)點
deleteNode () {
this.$emit("delete-node")
},
// 接收刪除子節(jié)點的指令并執(zhí)行刪除功能
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動態(tài)添加class可能帶來的問題解讀(被覆蓋)
文章討論了在使用Vue.js時,通過動態(tài)class修改元素樣式時可能會遇到的問題,當通過JavaScript動態(tài)添加類時,Vue的動態(tài)class會覆蓋掉通過JavaScript添加的類,導致樣式丟失,這個問題在實際開發(fā)中可能會遇到,尤其是在使用第三方框架2024-12-12
一次在vue中使用post進行excel表下載的實戰(zhàn)記錄
最近遇到了需求,覺著有必要給大家總結下,這篇文章主要給大家介紹了關于一次在vue中使用post進行excel表下載的實戰(zhàn)記錄,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-07-07
Vue3+ElementPlus el-date-picker設置可選時間范圍的示例代碼
在Vue3中使用Element Plus的el-date-picker組件設置可選時間范圍,你可以使用disabled-date屬性,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-07-07

