1.HTML页面渲染
构建三个面板,面板1渲染需要被拖动的节点树,面板2和面板3用于接收并展示被拖动到该区域的节点,且面板1和面板2必须是固定的高度(自适应的目前不适用,无法获取固定的 x,y 范围)。
代码如下:
<template>
<div class="app-container">
<!-- 面板1 -->
<div class="div1 normalDivStyle">
<!-- 数据库表及其字段 -->
<div class="fieldMenu normalMenuStyle">
<div class="title">面板1</div>
<el-tree
ref="tableTree"
:data="tableList"
show-checkbox
node-key="id"
:props="defaultProps"
draggable
:allow-drop="returnFalse"
@node-drag-end="handleDragend"
/>
</div>
</div>
<div class="div2 normalDivStyle">
<!-- 面板2 -->
<div class="xyMenu normalMenuStyle" style="height:100px">
<div class="title">面板2</div>
<div class="content">
<p>{{ xNodeArr.label }}</p>
</div>
</div>
<!-- 面板3 -->
<div class="xyMenu normalMenuStyle">
<div class="title">面板3</div>
<div class="content">
<p>{{ yNodeArr.label }}</p>
</div>
</div>
</div>
</div>
</template>
其中 draggable 表示是否开启节点拖拽功能,allow-drop 拖拽时判定目标节点能否被放置,node-drag-end 拖拽结束时(可能未成功)触发的事件,具体参考官方。
2.定义所需的变量
defaultProps: {
children: 'children',
label: 'label'
},
// 树形控件渲染数据
tableList: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1'
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}],
xNodeArr: {},//面板2接收
yNodeArr: {},//面板3接收
3.方法实现
主要获取面板1与面板2在浏览器中的 x 与 y 的位置范围,再根据拖拽结束时鼠标所在 x,y 位置来判断将节点放入哪个面板中。
// 拖拽结束时(可能未成功)触发的事件
handleDragend(draggingNode, endNode, position, event) {
// debugger
if (draggingNode.level === 2) {// 只拖拽第2级节点
// @mousemove='updateXY'//获取鼠标点击时的位置
// 根据拖拽结束时鼠标的坐标位置来判断将变量放入哪个面板中
if (event.x > 332 && event.x < 581 && event.y > 167 && event.y < 231) {// 面板1所在浏览器中x,y的区间范围
this.xNodeArr = {
tableName: draggingNode.parent.data.label,
label: draggingNode.data.label,
columnIndex: 'baseColumn'
}
} else if (event.x > 332 && event.x < 581 && event.y > 285 && event.y < 451) {// 面板2所在浏览器中x,y的区间范围
this.yNodeArr = {
tableName: draggingNode.parent.data.label,
label: draggingNode.data.label,
columnIndex: 'baseColumn'
}
} else {
this.$message({
type: 'warning',
message: '请将变量拖入对应的框中!'
})
}
}
},
returnFalse() {
return false
},
4.样式
<style lang="scss">
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.normalDivStyle{
float: left;
background-color: #fff;
padding: 15px;
box-shadow: 0 1px 1px rgb(0 0 0 / 10%);
border-top: 3px solid #d2d6de;
}
.normalMenuStyle{
border: 1px solid #EBEEF5;
border-radius: 4px;
overflow: auto;
display: inline-block;
vertical-align: middle;
-webkit-box-sizing: border-box;
box-sizing: border-box;
position: relative;
}
.title{
width:100%;
height:35px;
line-height:15px;
padding:10px;
background-color:#F5F7FA;
border-bottom: 1px solid #e4e4e5;
color:#409EFF;
font-size:14px;
// text-align: center;
font-weight: 700;
}
.content{
width:100%;
height: auto;
padding: 10px;
p{
margin: 0 0 10px 0;
font-size: 14px;
color: #606266;
}
}
.div1{
width: 14.5%;
position: absolute;
left: 20px;
top: 53px;
bottom: 25px;
overflow: hidden;
.fieldMenu{
width:100%;
height: 40%;
}
}
.div2{
width: 14.5%;
position: absolute;
left: 16.5%;
top: 53px;
bottom: 25px;
.xyMenu{
width:100%;
height: 200px;
margin-bottom: 20px;
}
}
</style>