Vue 树状结构控件

news2025/6/5 20:24:42

1、效果图如下所示:

2、网络请求的数据结构如下:

3、新建插件文件:menu-tree.vue,插件代码如下:

<template>
    <div class="root">
        <div class="parent" @click="onParentClick(parentItem)">
            <div class="parent-rectangle" :style="{ 'width': i == 1 ? '24px' : '32px' }" v-for="i in currentLevel - 1" :key="i"></div>
            <div class="parent-right">
                <img class="parent-icon" :src="getParentIconUrl()" @click.stop="changeExpandStatus()"/>
                <div class="parent-title" v-html="parentItem.text"></div>
            </div>
        </div>
        <div class="child" v-if="isShowChildList()">
            <MenuTree :parentItem="item" v-for="(item, index) in parentItem.children" :currentLevel="currentLevel + 1"
                :key="index" @onMenuTreeItemConfirm="onMenuTreeItemConfirm"></MenuTree>
        </div>
    </div>
</template>

<script>
export default {
    components: {
        MenuTree: () => import('./menu-tree.vue') // 引入自身作为子组件
    },
    props: {
        parentItem: {
            type: Object,
            default: {}
        },
        currentLevel: {
            type: Number,
            default: 1
        },
    },
    mounted() {},
    data() {
        return {
            treeMinUnitIconUrl: require('@/assets/images/icon-file.svg'),
            treeFoldedIconUrl: require('@/assets/images/icon-to-fold.svg'),
            treeExpandedIconUrl: require('@/assets/images/icon-to-expand.svg'),
        }
    },
    watch: {},
    methods: {
        isShowChildList() {
            return this.parentItem.expanded;
        },
        changeExpandStatus() {
            console.log("this.parentItem.childQty = " + this.parentItem.childQty);
            if (this.parentItem.childQty && this.parentItem.childQty > 0) {
                this.parentItem.expanded = !this.parentItem.expanded;
            }
        },
        getParentIconUrl() {
            if (this.currentLevel == 1) {
                return this.treeMinUnitIconUrl;
            }
            if (!this.parentItem.childQty || this.parentItem.childQty == 0) {
                return this.treeMinUnitIconUrl;
            }
            return this.parentItem.expanded ? this.treeFoldedIconUrl : this.treeExpandedIconUrl;
        },
        onParentClick(item) {
            if (this.currentLevel > 1) {
                item.currentLevel = this.currentLevel;
            }
            this.$emit("onMenuTreeItemConfirm", item);
        },
        onMenuTreeItemConfirm(item) {
            this.onParentClick(item);
        },
    },
}
</script>

<style scoped>
.root {
    width: 100%;
    min-height: 48px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.parent {
    min-height: 48px;
    width: 100%;
    display: flex;
    flex-direction: row;
    align-items: center;
}

.parent-rectangle {
    min-height: 48px;
}

.parent-right {
    min-height: 48px;
    min-width: 140px;
    display: flex;
    flex-direction: row;
    align-items: center;
}

.parent-icon {
    width: 24px;
    height: 24px;
}

.parent-title {
    width: calc(100% - 24px - 8px);
    min-height: 16px;
    text-align: left;
    line-height: 16px;
    font-size: 14px;
    margin-left: 8px;
}

.child {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
}
</style>

4、使用方法如下:

<template>
    <div class="root">
        <van-popup class="popup" v-model="showMenuTreePop" round position="bottom">
            <div class="popup-title">请选择行政区划</div>
            <div style="height: 60vh; width: 100%; overflow-y: scroll;">
                <MenuTree :parentItem="rootItem" :currentLevel="1" @onMenuTreeItemConfirm="onMenuTreeItemConfirm"></MenuTree>
            </div>
            <div class="table-bottom">
                <div class="table-bottom-btn color-green" @click="showMenuTreePop = false">取消</div>
            </div>
        </van-popup>
    </div>
</template>

<script>
import MenuTree from '@/components/menu-tree.vue';
export default {
    components: { MenuTree },
    data() {
        return {
            rootItem: {},
            showMenuTreePop: false,
        }
    },
    methods: {
        loadMenutreeDataList() {
            // 通过网络请求获取数据列表 res
            console.log("res = ", res);
            this.$set(this.rootItem, "children", res);
            this.$set(this.rootItem, "text", "行政区划");
            this.$set(this.rootItem, "expanded", true);
            this.$set(this.rootItem, "childQty", res ? res.length : 0);
            this.showMenuTreePop = true;// 打开弹窗
        },
        onMenuTreeItemConfirm(clickedItem) {
            // clickedItem 就是点击选中的数据项, 其 currentLevel 属性值就是其所处层级,如果层级是1,则表示点击的是根节点
            this.showMenuTreePop = false;// 关闭弹窗
        },
    }
}
</script>

<style scoped>
.root {
    width: 100%;
    height: 100vh;
}

.popup {
    width: 100%;
    background: #FFFFFF;
    border-radius: 16px;
}

.table-bottom {
    width: 100%;
    height: 71px;
    display: flex;
    flex-direction: row;
    align-items: center;
    border-top: solid 1px #E8E8E8;
}

.table-bottom-btn {
    min-width: 50px;
    height: 44px;
    flex: 1;
    color: #FFFFFF;
    font-size: 12px;
    line-height: 44px;
    border-radius: 22px;
    margin-left: 3%;
    margin-right: 3%;
    font-family: PingFangSC-Regular;
    font-weight: 400;
    text-align: center;
}

.color-green {
    color: #FFFFFF;
    background-color: #2DA541;
}
</style>

5、插件中使用到的资源文件如下:

1、icon-file.svg

<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716600220842" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19100" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M815.104 69.632q27.648 25.6 44.032 42.496t25.088 28.672 10.752 19.968 2.048 14.336l0 16.384-151.552 0q-10.24 0-17.92-7.68t-12.8-17.92-7.68-20.992-2.56-16.896l0-126.976 3.072 0q8.192 0 16.896 2.56t19.968 9.728 28.16 20.48 42.496 35.84zM640 129.024q0 20.48 6.144 42.496t19.456 40.96 33.792 31.232 48.128 12.288l149.504 0 0 577.536q0 29.696-11.776 53.248t-31.232 39.936-43.008 25.6-46.08 9.216l-503.808 0q-19.456 0-42.496-11.264t-43.008-29.696-33.28-41.984-13.312-49.152l0-696.32q0-21.504 9.728-44.544t26.624-42.496 38.4-32.256 45.056-12.8l391.168 0 0 128zM704.512 768q26.624 0 45.056-18.944t18.432-45.568-18.432-45.056-45.056-18.432l-384 0q-26.624 0-45.056 18.432t-18.432 45.056 18.432 45.568 45.056 18.944l384 0zM768 448.512q0-26.624-18.432-45.568t-45.056-18.944l-384 0q-26.624 0-45.056 18.944t-18.432 45.568 18.432 45.056 45.056 18.432l384 0q26.624 0 45.056-18.432t18.432-45.056z" p-id="19101" fill="#1296db"></path></svg>

2、icon-to-expand.svg

<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716600138280" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5120" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M880 112a32 32 0 0 1 32 32v736a32 32 0 0 1-32 32H144a32 32 0 0 1-32-32V144a32 32 0 0 1 32-32z m-40 72H184v656h656V184zM536 320c4.416 0 8 3.584 8 8V480h152c4.416 0 8 3.584 8 8v48a8 8 0 0 1-8 8H544v152a8 8 0 0 1-8 8h-48a8 8 0 0 1-8-8V544H328A8 8 0 0 1 320 536v-48c0-4.416 3.584-8 8-8H480V328c0-4.416 3.584-8 8-8z" fill="#1296db" fill-opacity=".65" p-id="5121"></path></svg>


3、icon-to-fold.svg

<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716600168259" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18002" xmlns:xlink="http://www.w3.org/1999/xlink" width="48" height="48"><path d="M880 112a32 32 0 0 1 32 32v736a32 32 0 0 1-32 32H144a32 32 0 0 1-32-32V144a32 32 0 0 1 32-32z m-40 72H184v656h656V184zM696 480c4.416 0 8 3.584 8 8v48a8 8 0 0 1-8 8h-368A8 8 0 0 1 320 536v-48c0-4.416 3.584-8 8-8z" fill="#1296db" fill-opacity=".65" p-id="18003"></path></svg>

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

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

相关文章

【LUT技术专题】图像自适应3DLUT代码讲解

本文是对图像自适应3DLUT技术的代码解读&#xff0c;原文解读请看图像自适应3DLUT文章讲解 1、原文概要 结合3D LUT和CNN&#xff0c;使用成对和非成对的数据集进行训练&#xff0c;训练后能够完成自动的图像增强&#xff0c;同时还可以做到极低的资源消耗。下图为整个模型的…

vscode使用“EIDE”和“Cortex-Debug”插件利用st-link插件实现程序烧写以及调试工作

第一步&#xff1a;安装vscode插件“EIDE”EIDE和“Cortex-Debug”。 第二步&#xff1a;配置EIDE 2.1安装“实用工具”&#xff1a; 2.2 EIDE插件配置&#xff1a;根据安装的keil C51 keil MDK IAR的相关路径设置 第三步&#xff1a;配置Cortex-Debug插件 点击settings.jso…

Spring @Value注解的依赖注入实现原理

Spring Value注解的依赖注入实现原理 一&#xff0c;什么是Value注解的依赖注入二&#xff0c;实现原理三&#xff0c;代码实现1. 定义 Value 注解2. 实现 InstantiationAwareBeanPostProcessor3. 实现 AutowiredAnnotationBeanPostProcessor4. 占位符解析逻辑5. 定义 StringVa…

三、kafka消费的全流程

五、多线程安全问题 1、多线程安全的定义 使用多线程访问一个资源&#xff0c;这个资源始终都能表现出正确的行为。 不被运行的环境影响、多线程可以交替访问、不需要任何额外的同步和协同。 2、Java实现多线程安全生产者 这里只是模拟多线程环境下使用生产者发送消息&…

Axure形状类组件图标库(共8套)

点击下载《月下倚楼图标库(形状组件)》 原型效果&#xff1a;https://axhub.im/ax9/02043f78e1b4386f/#g1 摘要 本图标库集锦精心汇集了8套专为Axure设计的形状类图标资源&#xff0c;旨在为产品经理、UI/UX设计师以及开发人员提供丰富多样的设计素材&#xff0c;提升原型设计…

20250530-C#知识:String与StringBuilder

String与StringBuilder string字符串在开发中经常被用到&#xff0c;不过在需要频繁对字符串进行增加和删除时&#xff0c;使用StringBuilder有利于提升效率。 1、String string是一种引用类型而非值类型&#xff08;某些方面像值类型&#xff09;使用“”进行两个string对象的…

从 Docker 到 Containerd:Kubernetes 容器运行时迁移实战指南

一、背景 Kubernetes 自 v1.24 起移除了 dockershim&#xff0c;不再原生支持 Docker Engine&#xff0c;用户需迁移至受支持的 CRI 兼容运行时&#xff0c;如&#xff1a; Containerd&#xff08;推荐&#xff0c;高性能、轻量级&#xff09; CRI-O&#xff08;专为 Kuberne…

uniapp中view标签使用范围

不止用于微信小程序。兼容型号&#xff0c;是uniapp内置组件之一&#xff0c;在uniapp中进行了跨平台适配。支持所有uniapp的平台。如微信小程序、h5、app、支付宝小程序

欢乐熊大话蓝牙知识14:用 STM32 或 EFR32 实现 BLE 通信模块:从0到蓝牙,你也能搞!

&#x1f680; 用 STM32 或 EFR32 实现 BLE 通信模块&#xff1a;从0到蓝牙&#xff0c;你也能搞&#xff01; “我能不能自己用 STM32 或 EFR32 实现一个 BLE 模块&#xff1f;” 答案当然是&#xff1a;能&#xff01;还能很帅&#xff01; &#x1f468;‍&#x1f3ed; 前…

IDEA 在公司内网配置gitlab

赋值项目链接 HTTPS 将HTTP的链接 ip地址换成 内网地址 例如&#xff1a;https:172.16.100.18/...... 如果出现需要需要Token验证的情况&#xff1a; 参考&#xff1a;Idea2024中拉取代码时GitLab提示输入token的问题_gitlab token-CSDN博客

黑马Java面试笔记之 微服务篇(业务)

一. 限流 你们项目中有没有做过限流?怎么做的? 为什么要限流呢? 一是并发的确大(突发流量) 二是防止用户恶意刷接口 限流的实现方式: Tomcat:可以设置最大连接数 可以通过maxThreads设置最大Tomcat连接数,实现限流,但是适用于单体架构 Nginx:漏桶算法网关,令牌桶算法自定…

通过WiFi无线连接小米手机摄像头到电脑的方法

通过WiFi无线连接小米手机摄像头到电脑的方法 以下是基于Scrcpy和DroidCam两种工具的无线连接方案&#xff0c;需提前完成开发者模式与USB调试的开启&#xff08;参考原教程步骤&#xff09;&#xff1a; 方法一&#xff1a;Scrcpy无线投屏&#xff08;无需手机端安装&#xf…

长短期记忆(LSTM)网络模型

一、概述 长短期记忆&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;网络是一种特殊的循环神经网络&#xff08;RNN&#xff09;&#xff0c;专门设计用于解决传统 RNN 在处理长序列数据时面临的梯度消失 / 爆炸问题&#xff0c;能够有效捕捉长距离依赖关系。…

CSS3美化页面元素

1. 字体 <span>标签 字体样式⭐ 字体类型&#xff08;font-family&#xff09; 字体大小&#xff08;font-size&#xff09; 字体风格&#xff08;font-style&#xff09; 字体粗细&#xff08;font-weight&#xff09; 字体属性&#xff08;font&#xff09; 2. 文本 文…

WPS 利用 宏 脚本拆分 Excel 多行文本到多行

文章目录 WPS 利用 宏 脚本拆分 Excel 多行文本到多行效果需求背景&#x1f6e0; 操作步骤代码实现代码详解使用场景注意事项总结 WPS 利用 宏 脚本拆分 Excel 多行文本到多行 在 Excel 工作表中&#xff0c;我们经常遇到一列中包含多行文本&#xff08;用换行符分隔&#xff…

AI“实体化”革命:具身智能如何重构体育、工业与未来生活

近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术的飞速发展正在重塑各行各业&#xff0c;而具身智能&#xff08;Embodied AI&#xff09;作为AI领域的重要分支&#xff0c;正逐渐从实验室走向现实应用。具身智能的核心在于让AI系统具备物理实体&#xff0c;能够与环…

R语言基础| 创建数据集

在R语言中&#xff0c;有多种数据类型&#xff0c;用以存储和处理数据。每种数据类型都有其特定的用途和操作函数&#xff0c;使得R语言在处理各种数据分析任务时非常灵活和强大&#xff1a; 向量&#xff08;Vector&#xff09;: 向量是R语言中最基本的数据类型&#xff0c;它…

Centos7搭建zabbix6.0

此方法适用于zabbix6以上版本zabbix6.0前期环境准备&#xff1a;Lamp&#xff08;linux httpd mysql8.0 php&#xff09;mysql官网下载位置&#xff1a;https://dev.mysql.com/downloads/mysql/Zabbix源码包地址&#xff1a;https://www.zabbix.com/cn/download_sourcesZabbix6…

Docker 部署前后端分离项目

1.Docker 1.1 什么是 Docker &#xff1f; Docker 是一种开源的 容器化平台&#xff0c;用于开发、部署和运行应用程序。它通过 容器&#xff08;Container&#xff09; 技术&#xff0c;将应用程序及其依赖项打包在一个轻量级、可移植的环境中&#xff0c;确保应用在不同计算…

云游戏混合架构

云游戏混合架构通过整合本地计算资源与云端能力&#xff0c;形成了灵活且高性能的技术体系&#xff0c;其核心架构及技术特征可概括如下&#xff1a; 一、混合架构的典型模式 分层混合模式‌ 前端应用部署于公有云&#xff08;如渲染流化服务&#xff09;&#xff0c;后端逻辑…