<template>
<div class="drag_folder_box">
<el-tree
draggable
node-key="uid"
:default-expanded-keys="defaultExpanded"
:indent="indentLeft"
:data="interiorList"
:props="treeOption"
:allow-drop="handleDragBehavior"
:allow-drag="handleAllowDrag"
@node-drag-start="handleDragStart"
@node-drag-enter="handleDragEnter"
@node-drag-leave="handleDragLeave"
@node-drag-over="handleDragOver"
@node-drag-end="handleDragEnd"
@node-drop="handleDrop"
@node-click="handleSwitchBillboard"
>
<template #default="{ data }">
<div class="tree_item">
<div class="item_title">
<template v-if="data.type === 'dir'">{{ data.label }}</template>
<template v-else>{{ data.label }}({{ data.creator }})</template>
</div>
<div class="item_operate">
<div class="operate_item" title="编辑" @click.stop="editBillboard(data)">
<el-icon :size="16">
<ele-Edit />
</el-icon>
</div>
<div class="operate_item" title="删除" @click.stop="deleteBillboard(data)">
<el-icon :size="16">
<ele-Delete />
</el-icon>
</div>
</div>
</div>
</template>
</el-tree>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import type Node from 'element-plus/es/components/tree/src/model/node'
import type { DragEvents } from 'element-plus/es/components/tree/src/model/useDragNode'
import type { AllowDropType, NodeDropType } from 'element-plus/es/components/tree/src/tree.type'
import type { IGetBillboardListTreeItem } from '@/types/billboard'
// #region 组件逻辑
interface IProps {
boardId?: number
list?: Array<IGetBillboardListTreeItem>
}
const props = withDefaults(defineProps<IProps>(), {
boardId: 0,
list: () => []
})
const emit = defineEmits(['edit', 'delete', 'switch', 'change'])
const treeOption = {
class: (data: IGetBillboardListTreeItem, node: Node) => {
if (data.id === props.boardId && data.type === 'dashboard') {
return 'on_tree_item'
} else if (data.type === 'dir') {
return 'folder'
} else {
return 'dashboard'
}
}
}
const interiorList = ref<Array<IGetBillboardListTreeItem>>([])
const defaultExpanded = ref<Array<string>>([])
const indentLeft = ref(10)
// #endregion
// #region 拖拽逻辑
watch(
() => props.list,
(newValue) => {
interiorList.value = newValue
},
{
deep: true,
immediate: true
}
)
// 节点开始拖拽时
const handleDragStart = (node: Node, ev: DragEvents) => {}
// 拖拽进入其他节点时
const handleDragEnter = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {}
// 拖拽离开某个节点时
const handleDragLeave = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {}
// 在拖拽节点时
const handleDragOver = (draggingNode: Node, dropNode: Node, ev: DragEvents) => {}
// 拖拽结束时
const handleDragEnd = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {}
// 拖拽成功时
const handleDrop = (draggingNode: Node, dropNode: Node, dropType: NodeDropType, ev: DragEvents) => {
emit('change', interiorList.value)
}
// 是否允许拖拽
const handleAllowDrag = (draggingNode: Node) => {
return true
}
// 拖拽行为判断
const handleDragBehavior = (draggingNode: Node, dropNode: Node, type: AllowDropType) => {
// 如果选中的节点不是看板 则不允许拖动到内部,只能是 'prev' 或 'next'
if (dropNode.data.type === 'dashboard') {
return type !== 'inner'
}
return true
}
// 编辑看板/文件夹
const editBillboard = (data: IGetBillboardListTreeItem) => {
emit('edit', data)
}
// 删除看板/文件夹
const deleteBillboard = (data: IGetBillboardListTreeItem) => {
emit('delete', data)
}
// 选择看板
const handleSwitchBillboard = (data: IGetBillboardListTreeItem) => {
if (data.type === 'dir') return
if (data.id === props.boardId) return
emit('switch', data)
}
// #endregion
// #region 生命周期
onMounted(() => {
interiorList.value = props?.list || []
if (props.boardId) {
defaultExpanded.value = []
interiorList.value.forEach((item) => {
if (item.children) {
if (item.children.find((item2) => item2.id === props.boardId) || item.children.length === 0) {
if (!defaultExpanded.value.includes(item.uid)) {
defaultExpanded.value.push(item.uid)
}
}
}
})
}
})
// #endregion
</script>
<style lang="scss" scoped>
.drag_folder_box {
width: 100%;
height: 100%;
background-color: #fff;
// 蓝色的线
&:deep(.el-tree__drop-indicator) {
height: 2px;
left: 0px !important;
}
// 重置样式
&:deep(.el-tree-node:focus > .el-tree-node__content) {
background-color: #e4f2ff !important;
}
&:deep(.el-tree-node__content) {
width: 100%;
height: auto;
border-bottom: 1px solid transparent;
box-sizing: border-box !important;
&:hover {
background-color: #e4f2ff !important;
}
&:focus {
background-color: #e4f2ff !important;
}
}
.tree_item {
width: calc(100% - 20px);
display: flex;
align-items: center;
height: 36px;
line-height: 36px;
&:hover {
background-color: #e4f2ff;
color: #3d90ff;
.item_operate {
opacity: 1;
}
}
.item_title {
width: calc(100% - 48px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.item_operate {
flex-shrink: 0;
opacity: 0;
width: 48px;
height: 100%;
display: flex;
align-items: center;
justify-content: space-around;
.operate_item {
width: 24px;
height: 100%;
display: flex;
align-items: center;
justify-content: space-around;
}
}
}
}
</style>
<!-- Tree的样式 -->
<style lang="scss">
.folder {
font-weight: bold;
color: #000000;
}
.dashboard {
font-weight: normal;
color: #606266;
}
.on_tree_item {
background-color: #e4f2ff !important;
color: #3d90ff !important;
}
.el-tree-node__expand-icon {
line-height: 36px !important;
height: 36px !important;
padding: 0px 2px !important;
}
.el-tree-node__expand-icon.expanded {
transform: rotate(0deg);
& svg {
transform: rotate(90deg);
}
}
</style>
没有合适的资源?快使用搜索试试~ 我知道了~
前端层级拖拽文件夹组件(Vue3+elementPlus的Tree组件实现)

共1个文件
vue:1个

需积分: 1 11 下载量 78 浏览量
2024-01-05
09:44:21
上传
评论
收藏 2KB ZIP 举报
温馨提示
功能:使用Vue3和ElementPlus的Tree组件,实现了一个具有创建、删除、重命名文件夹和文件功能的树形结构。用户可以通过拖拽操作来添加、移动或删除节点,同时在拖拽过程中显示辅助线。 能做到什么: 1. 创建、删除、重命名文件夹和文件:通过拖拽操作,用户可以在树形结构中创建、删除和重命名文件夹和文件。 2. 拖拽功能:支持将文件拖拽到文件夹中,或将文件夹拖拽到文件夹中,实现节点之间的移动。 3. 展开文件夹:点击文件夹节点时,可以展开显示其中的所有子节点。 4. 显示辅助线:在拖拽过程中,会显示一条辅助线,帮助用户更好地理解拖拽的方向和位置。
资源推荐
资源详情
资源评论

























格式:pdf 资源大小:43.8KB 页数:2






收起资源包目录


共 1 条
- 1
资源评论


冲浪的鹏多多

- 粉丝: 2178
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- 某供电公司项目管理部经理行为规范考评表格.doc
- 【开题报告】OA办公自动化系统.doc
- 环境空气质量标准---GB3095-1996.doc
- 射频前端领域竞争优势、全球基带芯片份额及全球射频前端市场规模发展趋势分析.docx
- 西打磨厂64号院第三进院四合院拆除方案.doc
- 北京某综合楼测量工施工技术交底.doc
- 肺栓塞课件徐滨.ppt
- 山东省市政工程预算员培训讲义p.doc
- 建筑施工企业精准物流管理.doc
- 注意力宣传推广家长讲座大纲万老师.doc
- 软件项目启动管理软件项目管理课件.ppt
- 探究互联网+时代乡村旅游的可持续发展对策.docx
- 第一章-动物的细胞和组织.pdf
- 大纲103页补充.doc
- [广东]塔吊使用应急预案.doc
- 高层住宅楼宇智能毕业设计开题报告.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
