树形菜单-vue3

2 篇文章 0 订阅
1 篇文章 0 订阅

基于vue3+element-plus,可自定义配置图标,可配置展开按钮及图标,实现自定义点击展开事件,另外还配置了可拖拽换位,解决element-plus折叠不能自动关闭字节点的问题。 

 实现效果如图所示

完整代码如下:

<!-- 树形菜单-自定义图标-自定义折叠功能 -->
<template>
	<div class="page">
		<el-tree
			style="width: 600px"
			:data="_data"
			:props="defaultProps"
			:expand-on-click-node="false"
			icon="ArrowDownBold"
			draggable
			:allow-drop="allowDrop"
		>
			<template #default="{ node, data }">
				<div class="left">
					<i class="iconfont" v-html="data.icon"></i><span>{{ data.ttt }}</span>
				</div>
				<div class="right" @click="handleNodeClick(node)">
					{{ node.childNodes.length ? (node.expanded ? '折叠' : '展开') : '' }}
					<span v-if="node.childNodes.length">
						<el-icon v-if="node.expanded"><CaretTop /></el-icon>
						<el-icon v-else><CaretBottom /></el-icon>
					</span>
				</div>
			</template>
		</el-tree>
	</div>
</template>
<script setup lang="ts">
import { reactive, nextTick } from 'vue';

const allowDrop = (draggingNode: any, dropNode: any, type: any) => {
	// 拖拽时判定目标节点能否成为拖动目标位置。
	// 如果返回 false ,拖动节点不能被拖放到目标节点。
	// type 参数有三种情况:'prev'、'inner' 和 'next',分别表示放置在目标节点前、插入至目标节点和放置在目标节点后
	return type !== 'inner'; // 不允许插入节点
};
const handleNodeClick = (node: any) => {
	console.log('node', node);
	nextTick(() => {
		// 下面这行就会实现
		node.expanded = !node.expanded; // 手动展开折叠点击的元素
		if (node.expanded == false) {
			zhankaiall(node.childNodes);
		}
	});
};

const zhankaiall = (arr: any) => {
	if (arr.length) {
		arr.map((item: any) => {
			item.expanded = false;
			if (item.childNodes.length) {
				zhankaiall(item.childNodes); // 递归关闭子节点
			}
		});
	}
};

let _data = reactive([
	{
		ttt: '一级标题111',
		expand: false,
		icon: '&#xe622;',
		children: [
			{
				ttt: '二级标题',
				expand: false,
				icon: '&#xe601;',
				children: [
					{
						ttt: '三级标题',
						expand: false,
						icon: '&#xe600;',
						children: [
							{
								ttt: '四级标题',
								expand: false,
								icon: '&#xe627;',
								children: [
									{
										ttt: '五级标题',
										icon: '&#xe64b;',
										expand: false,
									},
								],
							},
						],
					},
				],
			},
		],
	},
	{
		ttt: '一级标题222',
		expand: false,
		icon: '&#xe622;',
		children: [
			{
				ttt: '二级标题',
				expand: false,
				icon: '&#xe601;',
			},
		],
	},
	{
		ttt: '一级标题333',
		expand: false,
		icon: '&#xe622;',
		children: [
			{
				ttt: '二级标题',
				expand: false,
				icon: '&#xe601;',
			},
		],
	},
]);

const defaultProps = {
	children: 'children',
	label: 'ttt',
};
</script>
<style lang="scss">
.el-tree-node__expand-icon {
	display: none;
	// position: absolute;
	// right: 15px;
	// color: #fff;
	// svg {
	// 	transition: 0.3s;
	// }
	// &::before {
	// 	position: absolute;
	// 	left: -24px;
	// 	content: '展开';
	// 	font-style: normal;
	// }
	// &.expanded {
	// 	transform: none;
	// 	&::before {
	// 		content: '折叠';
	// 	}
	// 	svg {
	// 		transform: rotate(180deg);
	// 	}
	// }
}
.el-tree-node__content {
	background: #fd4a4a;
	padding: 8px 15px !important;
	box-sizing: content-box;
	margin-bottom: 10px;
	border-radius: 5px;
	display: flex;
	justify-content: space-between;
	color: #fff;
	cursor: default;
	.right {
		cursor: pointer;
	}
	&:hover {
		background: #ff2525;
	}
	.iconfont {
		margin-right: 5px;
	}
}
.el-tree-node:focus > .el-tree-node__content {
	background: #ff2525;
}
.el-tree-node__children {
	.el-tree-node > .el-tree-node__content {
		width: 545px;
		margin-left: 25px;
		background: rgb(241, 207, 54);
		border-radius: 5px;
	}
	.el-tree-node__children {
		.el-tree-node > .el-tree-node__content {
			width: 520px;
			margin-left: 50px;
			background: #409eff;
			border-radius: 5px;
		}
		.el-tree-node__children {
			.el-tree-node > .el-tree-node__content {
				width: 495px;
				margin-left: 75px;
				background: #67c23a;
				border-radius: 5px;
			}
			.el-tree-node__children {
				.el-tree-node > .el-tree-node__content {
					width: 470px;
					margin-left: 100px;
					background: rgb(37, 201, 119);
					border-radius: 5px;
				}
			}
		}
	}
}
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值