uniapp自定义树型结构数据弹窗,给默认选中的节点,禁用所有子节点

兼容H5、安卓App、微信小程序

实现逻辑:给默认选中节点的所有子节点添加一个disabled属性,以此禁用子节点。

/components/sonTreeNode/sonTreeNode.vue 封装成组件

<template>
	<view>
		<view :class="['item',item.is_level==1?'pL1':item.is_level==2?'pL2':'pL3']" v-for="(item, index) in treeList"
			:key="index">
			<view class="item--row" @click.stop="handleOpenClose(item, index)">
				<view class="icon-box">
					<u-icon :name="item.isOpen?'arrow-down-fill':'arrow-up-fill'" size="12" color="#a8abb2"
						v-if="item.children && item.children.length"></u-icon>
				</view>
				<view class="checkbox-box">
					<u-checkbox-group>
						<u-checkbox :disabled="item.disabled" :activeColor="themeColor" :label="item.name"
							:name="item.id" :checked='item.checked' usedAlone @change="changeCheckbox($event,item)" />
					</u-checkbox-group>
				</view>
			</view>

			<!-- 使用组件本身渲染子项 -->
			<view v-if="item.isOpen && item.children && item.children.length">
				<treeItem :list="item.children">
				</treeItem>
			</view>
		</view>
	</view>
</template>

<script>
	// 引入当前组件
	import treeItem from '../sonTreeNode/sonTreeNode'
	let activeTreeList = []
	export default {
		name: 'treeItem',
		components: {
			treeItem
		},
		// 接收列表数据
		props: {
			list: {
				type: Array,
				default: () => []
			},
			checkedId: {
				type: Array,
				default: () => []
			},
		},
		data() {
			return {
				themeColor: this.$themeColor,
				treeList: [],
			}
		},
		mounted() {
			this.setListUpOpen(this.list)
			this.treeList = this.list
			if (activeTreeList.length == 0) {
				activeTreeList = this.list
			}
		},
		methods: {
			// 全部展开
			setListUpOpen(list, isOpen = true) {
				list.forEach(item => {
					item.isOpen = isOpen
					// 数据回显,选中当前checked和禁用子节点 Start
					if (this.checkedId.includes(item.id)) {
						item.checked = true
						function setSonDisabled(son) {
							son.forEach(v => {
								v.disabled = true
								if (v?.children?.length > 0) {
									setSonDisabled(v.children)
								}
							})
						}
						if (item?.children?.length > 0) {
							setSonDisabled(item.children)
						}
					}
					// End
					if (item?.children?.length > 0) {
						this.setListUpOpen(item.children)
					}
				})
				return list
			},

			// 处理展开或收起
			handleOpenClose(item, index) {
				// 如果不存在isOpen属性就添加该属性。
				if (!item.hasOwnProperty('isOpen')) {
					item.isOpen = false
				}
				item.isOpen = !item.isOpen
				this.$forceUpdate()
			},

			// 禁用子节点
			disableNode(node, disabled) {
				node.forEach(item => {
					item.checked = false
					item.disabled = disabled
					if (item?.children?.length > 0) {
						this.disableNode(item.children, disabled)
					}
				})
				return node
			},

			setAssign(node, child) {
				node.forEach(item => {
					child.forEach(v => {
						if (item.id == v.id) {
							if (v.hasOwnProperty('checked')) {
								item.checked = v.checked
							}
							item.children = v.children
						}
					})
					if (item?.children?.length > 0) {
						this.setAssign(item.children, child)
					}
				})
				return node
			},

			changeCheckbox(isChecked, item) {
				let isHasChild = item?.children?.length > 0
				let oldTreeList = this.treeList
				if (isChecked) {
					item.checked = true
					if (isHasChild) {
						this.disableNode(item.children, true)
					}
				} else {
					item.checked = false
					if (isHasChild) {
						this.disableNode(item.children, false)
					}
				}
				activeTreeList = this.setAssign(activeTreeList, oldTreeList)
				if (isHasChild) {
					// #ifdef H5 ||APP-PLUS
					this.treeList = []
					this.$nextTick(() => {
						this.treeList = oldTreeList
					})
					// #endif

					// #ifdef MP-WEIXIN
					this.loadTreeList()
					// #endif
				}
			},
			getActiveTreeList() {
				return activeTreeList
			},
			cleatActiveTreeList() {
				activeTreeList = []
			},
		}
	}
</script>

<style scoped lang="scss">
	.pL1 {
		padding-left: 10rpx;
	}

	.pL2 {
		padding-left: 20rpx;
	}

	.pL3 {
		padding-left: 30rpx;
	}

	.item {
		margin-bottom: 15rpx;

		.item--row {
			display: flex;
			align-items: center;
			margin-bottom: 20rpx;

			.icon-box {
				width: 30rpx;
			}

			.checkbox-box {}
		}
	}
</style>

data.js 定义树形结构数据

const treeList = [{
		"id": 8,
		"name": "2栋",
		"pid": 0,
		"children": [{
				"id": 31,
				"name": "C单元",
				"pid": 8,
				"children": []
			},
			{
				"id": 30,
				"name": "B单元",
				"pid": 8,
				"children": []
			},
			{
				"id": 13,
				"name": "A单元",
				"pid": 8,
				"children": []
			}
		]
	},
	{
		"id": 9,
		"name": "3栋",
		"pid": 0,
		"children": [{
				"id": 27,
				"name": "B单元",
				"pid": 9,
				"children": [{
					"id": 28,
					"name": "6楼",
					"pid": 27,
				}]
			},
			{
				"id": 14,
				"name": "A单元",
				"pid": 9,
				"children": []
			}
		]
	},
	{
		"id": 11,
		"name": "4栋",
		"pid": 0,
		"children": [{
				"id": 29,
				"name": "B单元",
				"pid": 11,
				"children": []
			},
			{
				"id": 18,
				"name": "A单元",
				"pid": 11,
				"children": [{
					"id": 53,
					"name": "22222",
					"pid": 18,
				}]
			}
		]
	},
	{
		"id": 7,
		"name": "1栋",
		"pid": 0,
		"children": [{
				"id": 67,
				"name": "A单元",
				"pid": 7,
				"children": []
			},
			{
				"id": 66,
				"name": "B单元",
				"pid": 7,
				"children": []
			},
			{
				"id": 65,
				"name": "C单元",
				"pid": 7,
				"children": []
			},
		]
	}
]

export default treeList

页面文件

<template>
	<view class="">
		<u-button type="primary" @click="openPopup()">打开弹窗</u-button>
		<u-popup :show="showPopup" mode="bottom" :round="20" closeable @close="closePopup" :closeOnClickOverlay="false">
			<view class="popup-wrap">
				<view class="popup-title">
					选择子项目
				</view>
				<view class="popup-content">
					<sonTreeNode :list="treeList" ref="sonTreeNodeRef" :checkedId="checkedId"
						v-if="treeList.length>0" />
				</view>
				<view class="popup-footer">
					<view class="btn-box1">
						<u-button @click="closePopup()">取消</u-button>
					</view>
					<view class="btn-box2">
						<u-button type="primary" @click="confirmPopup()">确定</u-button>
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
	import Vue from 'vue'
	import sonTreeNode from '@/packageD/components/sonTreeNode/sonTreeNode.vue'
	import treeList from "./data.js"
	export default {
		components: {
			sonTreeNode
		},
		data() {
			return {
				treeList: [],
				showPopup: false,
				checkedId: [13, 18, 7, 28]
			};
		},
		onLoad() {},
		onUnload() {
			// #ifdef MP-WEIXIN
			this.clearInstance()
			// #endif
		},
		mounted() {
			// #ifdef MP-WEIXIN
			Vue.prototype.loadTreeList = this.loadTreeList;
			// #endif
		},
		methods: {
			clearInstance() {
				// 清除实例的逻辑
				this.$delete(Vue.prototype, 'loadTreeList');
			},
			loadTreeList() {
				this.$refs.sonTreeNodeRef.treeList = []
				this.$nextTick(() => {
					this.$refs.sonTreeNodeRef.treeList = this.$refs.sonTreeNodeRef.getActiveTreeList()
				})
			},
			openPopup(item, index) {
				this.treeList = treeList
				this.showPopup = true
			},
			confirmPopup() {
				let treeList = this.$refs.sonTreeNodeRef.treeList
				console.log("选中的id=", this.getCheckedIdArr(treeList));
				this.checkedId = this.getCheckedIdArr(treeList)
				this.closePopup()
			},
			closePopup() {
				this.$refs.sonTreeNodeRef.cleatActiveTreeList()
				this.showPopup = false
				this.treeList = []
			},
			getCheckedIdArr(node, arr = []) {
				node.forEach(item => {
					if (item.checked) {
						arr.push(item.id)
					}
					if (item?.children?.length > 0) {
						this.getCheckedIdArr(item.children, arr)
					}
				})
				return arr
			},

		},
	}
</script>

<style lang="scss" scoped>
	.popup-wrap {
		padding: 20rpx 40rpx;

		.popup-title {
			font-size: 36rpx;
			text-align: center;
		}

		.popup-content {
			margin-top: 20rpx;
			height: 800rpx;
			overflow-y: auto;
		}

		.popup-footer {
			display: flex;
			justify-content: space-between;

			.btn-box1,
			.btn-box2 {
				width: 48%;
			}
		}
	}
</style>

效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940043.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

运维工程师面试系统监控与优化自动化与脚本云计算的理解虚拟化技术的优点和缺点

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…

【GCC】2015: draft-alvestrand-rmcat-congestion-03 机器翻译

腾讯云的一个分析,明显是看了这个论文和草案的 : 最新的是应该是这个 A Google Congestion Control Algorithm for Real-Time Communication draft-ietf-rmcat-gcc-02 下面的这个应该过期了: draft-alvestrand-rmcat-congestion-03

web自动化测试知识总结

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、自动化测试基本介绍 1、自动化测试概述&#xff1a; 什么是自动化测试&#xff1f;一般说来所有能替代人工测试的方式都属于自动化测试&#xff0c;即通过工…

进程间通信方式---消息队列(System V IPC)

进程间通信方式—消息队列&#xff08;System V IPC&#xff09; 文章目录 进程间通信方式---消息队列&#xff08;System V IPC&#xff09;消息队列1.消息队列进程间通信原理2.msgget 系统调用3.msgsnd 系统调用4.msgrcv 系统调用5.msgctl 系统调用6.函数使用案例7.实现生产者…

python学opencv|读取图像(十七)认识alpha通道

【1】引言 前序学习进程中&#xff0c;我们已经掌握了RGB和HSV图像的通道拆分和合并&#xff0c;获得了很多意想不到的效果&#xff0c;相关链接包括且不限于&#xff1a; python学opencv|读取图像&#xff08;十二&#xff09;BGR图像转HSV图像-CSDN博客 python学opencv|读…

Unity Post请求发送fromdata数据content-type

wwwfrom 的 headers["Content-Type"]修改 错误代码&#xff1a; WWWForm form new WWWForm(); if (form.headers.ContainsKey("Content-Type")) {string boundary string.Format("--{0}", DateTime.Now.Ticks.ToString("x"));form…

服务平滑发布与线上验证

发布策略可分为&#xff1a; 蓝绿发布&#xff1a;将新版本服务器全部发好后&#xff0c;将旧版本服务器的流量统一切换到新版本上灰度发布&#xff08;金丝雀发布&#xff09;&#xff1a;是一种滚动发布方式&#xff0c;首先部署部分新版本服务器&#xff0c;将部分流量切到…

【数据安全】如何保证其安全

数据安全风险 数字经济时代&#xff0c;数据已成为重要的生产要素。智慧城市、智慧政务的建设&#xff0c;正以数据为核心&#xff0c;推动城市管理的智能化和公共服务的优化。然而&#xff0c;公共数据开放共享与隐私保护之间的矛盾日益凸显&#xff0c;如何在确保数据安全的…

ai论文生成器:分享8款AI一键生成论文的写作软件

在撰写毕业论文的过程中&#xff0c;高效利用各类软件工具可以极大地提升写作效率与质量。以下是八个免费的神器软件工具&#xff0c;它们各自在论文撰写、文献管理、语法校对、数据可视化等方面发挥着重要作用。希望这些推荐能帮助你顺利完成毕业论文的写作。 千笔AI论文&…

白话AI大模型(LLM)原理

大模型&#xff08;例如 GPT-4或类似的深度学习模型&#xff09;是基于神经网络的系统&#xff0c;用于理解、生成文本、图像或其他数据类型。其工作原理可以分为以下几个核心步骤&#xff0c;我将通过易于理解的例子逐一解释。 1. 神经网络的基本概念 大模型背后有一个非常庞…

数据压缩比 38.65%,TDengine 重塑 3H1 的存储与性能

小T导读&#xff1a;这篇文章是“2024&#xff0c;我想和 TDengine 谈谈”征文活动的三等奖作品之一。作者通过自身实践&#xff0c;详细分享了 TDengine 在高端装备运维服务平台中的应用&#xff0c;涵盖架构改造、性能测试、功能实现等多个方面。从压缩效率到查询性能&#x…

【Prometheus 】【实战篇(四)】Node Exporter安装方式(含一键安装脚本)及重要监控指标一览

目录 一、Node Exporter 1.8.2安装步骤详解1、下载 Node Exporter 安装包2、解压下载的文件3、将 Node Exporter 移动到 /usr/local/bin/4、创建一个专用的系统用户5、创建 systemd 服务文件6、重新加载 systemd 配置7、启动并启用 Node Exporter 服务8、检查 Node Exporter 状…

Qt之串口设计-线程实现(十二)

Qt开发 系列文章 - Serial-port&#xff08;十二&#xff09; 目录 前言 一、SerialPort 二、实现方式 1.创建类 2.相关功能函数 3.用户使用 4.效果演示 5.拓展应用-实时刷新 总结 前言 Qt作为一个跨平台的应用程序开发框架&#xff0c;在串口编程方面提供了方便易用…

信号处理相关的东东(学习解惑)

信号处理相关的东东&#xff08;学习解惑&#xff09; 所有内容学习自知乎专栏&#xff0c;https://www.zhihu.com/column/xinhao&#xff0c;写的很好&#xff0c;值得反复学习 时频域分析的一些常用概念 FROM&#xff1a;https://zhuanlan.zhihu.com/p/35742606 1、相加性…

使用 UniApp 在微信小程序中实现 SSE 流式响应

概述 服务端发送事件(Server-Sent Events, SSE)是一种允许服务器向客户端推送实时更新的技术。SSE 提供了一种单向的通信通道,服务器可以持续地向客户端发送数据,而不需要客户端频繁发起请求。这对于需要实时更新的应用场景非常有用。 流式传输的特点是将数据逐步传输给客…

【数据结构】八大排序

目录 一、直接插入排序 二、希尔排序 三、选择排序 四、堆排序 五、冒泡排序 六、快速排序 七、归并排序 八、计数排序 稳定性结论 稳定性&#xff1a;排序后相同元素之间的相对顺序是否保持不变。 一、直接插入排序 基本思想&#xff1a;通过构建有序序列&#xff…

线程池ForkJoinPool详解

由一道算法题引发的思考 算法题&#xff1a;如何充分利用多核CPU的性能&#xff0c;快速对一个2千万大小的数组进行排序&#xff1f; 这道算法题可以拆解来看&#xff1a; 1&#xff09;首先这是一道排序的算法题&#xff0c;而且是需要使用高效的排序算法对2千万大小的数组…

python08-序列02-字典dict、集合set

一、字典&#xff08;dict&#xff09;&#xff1a;可变数据类型 1-1、字典的特点 字典是可变数据类型&#xff08;list也是&#xff09;&#xff0c;具有增、删、改等一系列的操作&#xff1b;字典中的元素是无序的&#xff08;hash&#xff09;key必须唯一&#xff0c;value…

【Java项目】基于SpringBoot的【旅游管理系统 】

【Java项目】基于SpringBoot的【旅游管理系统 】 技术简介&#xff1a;本系统使用JAVA语言开发&#xff0c;采用B/S架构、Spring Boot框架、MYSQL数据库进行开发设计。 系统简介&#xff1a;&#xff08;1&#xff09;管理员功能&#xff1a;可以管理个人中心、用户管理、景区分…

UE5 跟踪能力的简单小怪

A、思路 1、用素材的骨骼网格体创建小怪BP&#xff0c;绑定新的小怪控制器。 2、控制器的事件开始时&#xff0c;获取玩家状态&#xff0c;指定AI小怪自动向玩家移动。 复杂的AI需要用强大功能如黑板、行为树。 而简单的AI则可以用简单方法实现&#xff0c;杀鸡不用牛刀。视…