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

news2024/12/22 0:31:05

兼容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>

效果图

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

水仙花数(流程图,NS流程图)

题目&#xff1a;打印出所有的100-999之间的"水仙花数"&#xff0c;并画出流程图和NS流程图。所谓"水仙花数"是指一个三位数&#xff0c;其各位数字立方和等于该数本身。例如&#xff1a;153是一个"水仙花数"&#xff0c;因为1531的三次方&#…

【C++读写.xlsx文件】OpenXLSX开源库在 Ubuntu 18.04 的编译、交叉编译与使用教程

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a; 2024-12-17 …

Kioptix Level 2靶场练习保姆级---春不晚

1.将靶机导入至vm中 首先将靶机的网络设置为nat模式&#xff0c;然后在kali中使用arp-scan命令查找靶机ip 靶机ip为&#xff1a;61.139.2.130 arp-scan -l 2.使用nmap扫描目标ip的端口 nmap -p- 61.139.2.130 3.对存在端口进行服务版本和、系统版本、默认脚本检测 nmap -p…

电子元器件与电路之-MOS管的介绍和作用

一、基本概念 MOS 管&#xff0c;或MOSFET&#xff0c;全称是Metal-Oxide-Semiconductor Field-Effect Transistor&#xff08;金属 - 氧化物 - 半导体场效应晶体管&#xff09;。和三极管利用电流控制电流不同&#xff0c;它是一种利用电场效应来控制电流的半导体器件。和三级…

异地组网最简单的方法

01、使用硬件路由器的VPN功能 这是一种相对简单且常用的异地组网方法。你需要有支持VPN功能的路由器&#xff0c;如华硕、中兴等品牌。在主站点的路由器上配置VPN服务器&#xff0c;并在异地设备上通过操作系统自带的VPN连接功能添加一个VPN连接&#xff0c;输入主站点路由器的…

【GO环境安装】mac系统+GoLand使用

文章目录 下载安装包环境配置GoLandGo Modules 下载安装包 地址&#xff1a;GO下载地址 下载好后直接进行安装&#xff1a; 进入terminal&#xff0c;查看是否安装成功&#xff1a; 环境配置 在文稿下面创建工作目录&#xff1a; 在文稿下新建Go_Works文件夹&#xff0c;在…

点击数字层级从 admin.vue 跳转到 inviter-list.vue 组件

文章目录 1、admin.vue2、inviter-list.vue 1、admin.vue 好的&#xff0c;我们来分析一下代码中“层级”这一列的逻辑&#xff0c;并探讨它与后端的关联。 “层级” 列的逻辑 在您的代码中&#xff0c;“层级”列的渲染逻辑如下&#xff1a; <el-table-columnalign&quo…

LabVIEW实时信号采集与频谱分析

系统通过LabVIEW与PXIe硬件结合&#xff0c;实现高精度模拟信号的实时采集、频谱分析与可视化显示。核心功能包括采样率配置、快速傅里叶变换&#xff08;FFT&#xff09;、功率谱图生成及动态缩放调整&#xff0c;同时支持信号平均与噪声抑制。系统设计灵活&#xff0c;适用于…

【ComfyUI + 铅笔素描画风】艺术家DaTou发布了的彩色铅笔素描风格生成(真实感超强)

发布时间&#xff1a;2024年12月09日 项目主页&#xff1a;https://hf-mirror.com/Datou1111/shou_xin 基础模型&#xff1a;flux.1-dev comfyui工作流下载&#xff1a;https://pan.baidu.com/s/1FrLQ4o8ldckKwhIrN1Pv7g?pwd1220 自己测试 官方效果 生成猫猫 shou_xin, a m…

洛谷 B3644 【模板】拓扑排序 / 家谱树 C语言

题目&#xff1a; https://www.luogu.com.cn/problem/B3644 题目描述 有个人的家族很大&#xff0c;辈分关系很混乱&#xff0c;请你帮整理一下这种关系。给出每个人的后代的信息。输出一个序列&#xff0c;使得每个人的后辈都比那个人后列出。 输入格式 第 1 行一个整数 …

unity接入coze智能体

官网链接 coze智能体创建、设置 点击创建–选着智能体&#xff0c;随便起一个名字&#xff0c;就可以了 添加令牌 把随便起一个名字&#xff0c;设置时间&#xff0c;把所有选项都勾选上&#xff0c;一定要勾选所有团队空间&#xff0c;否则无法点击确定。 点击确定后&a…

EE308FZ_Sixth Assignment_Beta Sprint_Sprint Essay 3

Assignment 6Beta SprintCourseEE308FZ[A] — Software EngineeringClass Link2401_MU_SE_FZURequirementsTeamwork—Beta SprintTeam NameFZUGOObjectiveSprint Essay 3_Day5-Day6 (12.15-12.16)Other Reference1. WeChat Mini Program Design Guide 2. Javascript Style Guid…

国内主流的工程项目管理软件有哪些?

随着科技的发展&#xff0c;工程管理软件已经成为了工程管理的重要工具。在国内&#xff0c;有许多优秀的工程管理软件&#xff0c;它们可以帮助我们更好地管理工程项目。那么&#xff0c;你知道有哪些工程管理软件吗&#xff1f;下面就让我们一起来盘点一下。 1、广联达 广联…

网络变压器如何识别电路

1. 基本符号的理解 曲线&#xff1a;表示变压器的线圈&#xff08;windings&#xff09;&#xff0c;每个曲线代表一个独立的线圈。 直线&#xff1a;用于连接不同的元件或引脚&#xff0c;表明电流路径。 2. 关键标注解释 CT&#xff08;Center Tap&#xff09;&#xff1a;中…

【原生js案例】ajax的简易封装实现后端数据交互

ajax是前端与后端数据库进行交互的最基础的工具&#xff0c;第三方的工具库比如jquery,axios都有对ajax进行第二次的封装&#xff0c;fecth是浏览器原生自带的功能&#xff0c;但是它与ajax还是有区别的&#xff0c;总结如下&#xff1a; ajax与fetch对比 实现效果 代码实现 …

免费开源!推荐一款网页版数据库管理工具!

免费开源&#xff01;推荐一款网页版数据库管理工具&#xff01; DBGate 是一个开源的数据库管理工具&#xff0c;DBGate 的最大特点是可以 Web 访问&#xff01;&#xff0c;轻松实现一台机器部署&#xff0c;所有人使用&#xff01; 无论是 MySQL、PostgreSQL、SQLite 还是…

主要是使用#includenlohmannjson.hpp时显示找不到文件,但是我文件已正确导入visual studio配置,也保证文件正确存在

问题&#xff1a; 主要是在项目配置中包括了C/C配置中文件位置&#xff0c;但是没有把nlohmann上一级的目录包括进去&#xff0c;导致#include"nlohmann/json.hpp"找不到文件位置 解决&#xff1a; 加上上一级目录到附加包含目录 596513661)] 总结&#xff1a; 找不…

智慧公交指挥中枢,数据可视化 BI 驾驶舱

随着智慧城市的蓬勃发展&#xff0c;公共交通作为城市运营的核心枢纽&#xff0c;正朝着智能化和数据驱动的方向演进。通过整合 CAN 总线技术(Controller Area Network&#xff0c;控制器局域网总线)、车载智能终端、大数据分析及处理等尖端技术&#xff0c;构建的公交“大脑”…

[c++11(二)]Lambda表达式和Function包装器及bind函数

1.前言 Lambda表达式着重解决的是在某种场景下使用仿函数困难的问题&#xff0c;而function着重解决的是函数指针的问题&#xff0c;它能够将其简单化。 本章重点&#xff1a; 本章将着重讲解lambda表达式的规则和使用场景&#xff0c;以及function的使用场景及bind函数的相关使…

redis数据类型:list

list 的相关命令配合使用的应用场景&#xff1a; 栈和队列&#xff1a;插入和弹出命令的配合&#xff0c;亦可实现栈和队列的功能 实现哪种数据结构&#xff0c;取决于插入和弹出命令的配合&#xff0c;如左插右出或右插左出&#xff1a;这两种种方式实现先进先出的数据结构&a…