指引型树型组件的封装

news2024/11/20 10:32:04

最近,由于业务的需要,需要做一个指向形树型组件。在寻找各种文章后,终于有了思路。🤒🤒🤒

树型组件的思路主要是递归。谈到递归,我们首先要有递归的出口。递归的出口就是没有孩子节点了。这个时候,我们就是叶子节点。

实现效果图:
在这里插入图片描述

1.dom结构

树型组件肯定由两部分构成,一部分是节点本身,另一部分为孩子节点。

<div v-for="(item, index) in data" :key="index" class="grandFather_item">

            <!-- 父类 -->
            <div class="father" :class="{'isRoot':deep===1}" @click="handleExplain(index)" style="line-height: 30px;height: 30px;">{{ item.title }}</div>
            <!-- 如果有子类,那么将子类传过去 -->
            <div class="children" v-if="item.children && item.children.length !== 0" v-show="item.isExplain">
                <Tree :data="item.children" :deep="deep + 1"></Tree>
            </div>
        </div>

这样,基本的显示就能够出来了。

2.缩进问题

因为我们每往下一级,我们就得往右边缩进一段距离。因此,我们的孩子肯定要包括在上一层的某个节点当中。因此需要给上述代码再包裹一层DOM结构。(在设置padding-left的时候内边距是累加的)。

 <div class="grandFather" :class="{ 'isRoot': deep === 1 }">
        <div v-for="(item, index) in data" :key="index" class="grandFather_item">

            <!-- 父类 -->
            <div class="father" :class="{'isRoot':deep===1}" @click="handleExplain(index)" style="line-height: 30px;height: 30px;">{{ item.title }}</div>
            <!-- 如果有子类,那么将子类传过去 -->
            <div class="children" v-if="item.children && item.children.length !== 0" v-show="item.isExplain">
                <Tree :data="item.children" :deep="deep + 1"></Tree>
            </div>
        </div>
    </div>

3.指引线

这里,我采用的思路是结合一个dom元素和一个伪元素进行布局。

dom元素主要是进行竖线(根据每一个类的高来布局)。伪元素进行横线(自己设)。然后计算边距。

<div class="grandFather" :class="{ 'isRoot': deep === 1 }">
        <div v-for="(item, index) in data" :key="index" class="grandFather_item">
            <div class="line"></div>
            <!-- 父类 -->
            <div class="father" :class="{'isRoot':deep===1}" @click="handleExplain(index)" style="line-height: 30px;height: 30px;">{{ item.title }}</div>
            <!-- 如果有子类,那么将子类传过去 -->
            <div class="children" v-if="item.children && item.children.length !== 0" v-show="item.isExplain">
                <Tree :data="item.children" :deep="deep + 1"></Tree>
            </div>
        </div>
    </div>

如果要设置点状,等形状,可以采用边框的形式来做。

最后代码如下

Tree.vue

<template>
    <div class="grandFather" :class="{ 'isRoot': deep === 1 }">
        <div v-for="(item, index) in data" :key="index" class="grandFather_item">
            <div class="line"></div>
            <!-- 父类 -->
            <div class="father" :class="{'isRoot':deep===1}" @click="handleExplain(index)" style="line-height: 30px;height: 30px;">{{ item.title }}</div>
            <!-- 如果有子类,那么将子类传过去 -->
            <div class="children" v-if="item.children && item.children.length !== 0" v-show="item.isExplain">
                <Tree :data="item.children" :deep="deep + 1"></Tree>
            </div>
        </div>
    </div>
</template>
<script setup >
// import Tree from './Tree.vue'
import { onMounted, ref } from 'vue'
const props = defineProps(['data', 'deep']); // deep是用来监听深度的.
const acceptData = ref([])
onMounted(() => {
    acceptData.value = props.data
    for (let item of acceptData.value) {
        if (item['isExplain'] === 'undefined') {
            item['isExplain'] = false; // 默认是不展开的
        }
    }
    console.log('acceptData.value', acceptData.value);

})
const handleExplain = (index) => {
    console.log('index', index);
    console.log(acceptData.value[index])
    acceptData.value[index]['isExplain'] = !acceptData.value[index]['isExplain']
}
</script>
<style lang='scss' scoped>
.grandFather {
    height: 100%;
    padding-left: 20px;

    .grandFather_item {
        height: 100%;
        position: relative;

        .line {
            width: 0px;
            border-right:1px dotted  black;
            height: calc(100% - 45px);
            position: absolute;
            left: 2px;
            top: 30px;
        }

        .father {
            position: relative;
            cursor: pointer;
        }

        .father::before {
            position: absolute;
            left: -18px;
            top: 15px;
            content: '';
            display: block;
            width: 16px;
            height: 0px;
            border-top: 1px dotted black;
            // background-color: black;
        }
        .isRoot::before {
            display: none;
        }
    }

    position: relative;

    .line {
        height: 100%;
        width: 1px;
        position: absolute;
    }
}



</style>

App.vue调用组件

<script setup>
import Tree from './components/Tree.vue';
import { ref } from 'vue';
const data = ref([{
  title: 'parent 1',
  key: '0-0',
  children: [
    {
      title: 'parent 1-0',
      key: '0-0-0',
      children: [
        { title: 'leaf', key: '0-0-0-0' },
        {
          key: '0-0-0-1',
          title:'叶子啊'
        },
        { title: 'leaf', key: '0-0-0-2' },
      ],
    },
    {
      title: 'parent 1-1',
      key: '0-0-1',
      children: [{ title: 'leaf', key: '0-0-1-0' }],
    },
    {
      title: 'parent 1-2',
      key: '0-0-2',
      children: [
        { title: 'leaf 1', key: '0-0-2-0' },
        {
          title: 'leaf 2',
          key: '0-0-2-1',
        },
      ],
    },
  ],
},
{
  title: 'parent 2',
  key: '0-1',
  children: [
    {
      title: 'parent 2-0',
      key: '0-1-0',
      children: [
        { title: 'leaf', key: '0-1-0-0' },
        { title: 'leaf', key: '0-1-0-1' },
      ],
    },
  ],
},
])
</script>

<template>
  <div>
    <Tree :data="data" :deep="1"></Tree>
  </div>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}

.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}

.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

最后大家如果有更好的想法,欢迎在评论区留言!🤓🤓🤓

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

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

相关文章

微博情绪分类

引自&#xff1a;https://blog.csdn.net/no1xiaoqianqian/article/details/130593783 友好借鉴&#xff0c;总体抄袭。 所需要的文件如下&#xff1a;https://download.csdn.net/download/m0_37567738/88340795 import os import torch import torch.nn as nn import numpy a…

pyqt与opencv-qt冲突解决办法

问题&#xff1a;pyqt显示不出界面 问题分析&#xff1a; 根据报错可以看出程序找到了libxcb.so&#xff0c;但是由于某些原因并不能够调用该驱动&#xff0c;这是因为pyqt5与opencv里的qt差生了冲突&#xff0c;这说明opencv内部的插件与pyqt5所使用的插件不兼容&#xff0c;因…

Elasticsearch 快速开始

Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎。 查询 &#xff1a; Elasticsearch 允许执行和合并多种类型的搜索 — 结构化、非结构化、地理位置、度量指标 — 搜索方式随心而变。分析 &#xff1a; 找到与查询最匹配的十个文档是一回事。但是如果面对的是…

zemax场曲与消场曲

场曲&#xff0c;像场弯曲&#xff0c;指的是平面物体通过透镜系统后&#xff0c;所有平面物点聚焦后的像面和理想平面不重合。 呈现一个弯曲的像面 单透镜为例&#xff1a; 此时聚焦显然不在一个平面上&#xff1a; 点列图可以观察到场曲的存在&#xff1a; 我们引入实际图…

R拒绝访问的解决方案

Win11系统 安装rms的时候报错&#xff1a; Error in loadNamespace(j <- i[[1L]], c(lib.loc, .libPaths()), versionCheck vI[[j]]) : namespace Matrix 1.5-4.1 is already loaded, but > 1.6.0 is required## 安装rms的时候报错&#xff0c;显示Matrix的版本太低…

Linux日志管理-logrotate(crontab定时任务、Ceph日志转储)

文章目录 一、logrotate概述二、logrotate基本用法三、logrotate运行机制logrotate参数 四、logrotate是怎么做到滚动日志时不影响程序正常的日志输出呢&#xff1f;Linux文件操作机制方案一方案二 五、logrotate实战--Ceph日志转储参考 一、logrotate概述 logrotate是一个用于…

Java 华为真题-选修课

需求&#xff1a; 现有两门选修课&#xff0c;每门选修课都有一部分学生选修&#xff0c;每个学生都有选修课的成绩&#xff0c;需要你找出同时选修了两门选修课的学生&#xff0c;先按照班级进行划分&#xff0c;班级编号小的先输出&#xff0c;每个班级按照两门选修课成绩和的…

下载CentOS ISO镜像 (一)

总目录 https://preparedata.blog.csdn.net/article/details/132877836 文章目录 总目录一、下载CentOS 镜像 一、下载CentOS 镜像 官网下载&#xff1a;https://www.centos.org/download/ Centos Linux 和 CentOS Stream 的区别&#xff1a;https://www.centos.org/cl-vs-cs…

设计模式(2) - 创建型模式

创建型模式指的是 创建对象 或是 获取实例 的方式。 1、工厂模式 平时写一些简单的代码可能会直接用 new 创建出一个对象&#xff0c;但是实际在阅读一些功能比较多、规模比较庞大的工程时&#xff0c;可能会发现有多个类继承于同一个基类的情况&#xff0c;它们拥有同样的接口…

删除安装Google Chrome浏览器时捆绑安装的Google 文档、表格、幻灯片、Gmail、Google 云端硬盘、YouTube网址链接(Mac)

删除安装Google Chrome浏览器时捆绑安装的Google 文档、表格、幻灯片、Gmail、Google 云端硬盘、YouTube网址链接(Mac) Mac mini操作系统&#xff0c;安装完 Google Chrome 浏览器以后&#xff0c;单击 启动台 桌面左下角的“显示应用程序”&#xff0c;我们发现捆绑安装了 Goo…

ArcGis10.8安装教程!

1、找到arcgis10.8中文安装包和Crack破解文件夹 2、运行"ArcGIS.exe"程序&#xff0c;进入安装向导&#xff1b;默认路径点下一步 3、注意&#xff0c;需要Python 2.7、Numpy、Matplotlib的支持 4、建议取消此处的勾选&#xff0c;开始进行安装 5、安装完成 6、…

【npm】npm私有库的使用-绑定

注册npm账户 输入基本信息 验证 收一次性验证码 登录 本地绑定 全局绑定了其他的私有库 若要在专门发包的项目中&#xff0c;发包到自己的私有库&#xff0c;需要在项目文件夹中创建一个.npmrc文件 创建文件 可以直接在项目目录下输入touch .npmrc创建文件 文件内容 regi…

C++之保存编译全部中间文件(二百一十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

JavaScript学习笔记03

JavaScript笔记03 流程控制 if 判断 和 Java 中if语句的使用方法相同。例&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script>"use strict"…

OPCAE扫盲

目录 1 基本概念 1.1 服务器/客户端 1.2 区域 1.3 报警/条件 1.4 事件 2 条件概念 2.1 子条件 2.2 OPCConditions属性 2.3 Condition质量 2.4 OPCSubConditions属性 2.5 Condition定义 2.6 严重性 2.7 Condition启用/禁用 2.8 Area启用/禁用 2.9 Condition状态集…

域控操作一:更换域用户桌面背景

1,创建背景图片文件夹并设置共享文件夹&#xff1a; 创建文件夹&#xff0c;将图片放进去&#xff0c;设置共享&#xff0c;权限改为Everyone 2&#xff0c;打开域控服务器设置组策略 在需要的组织单位OU内创建GPO设置名字为统一桌面背景 用户配置–管理模板–桌面–桌面 Act…

期权怎样的加仓才是合理的加仓?

期权加仓的手法是期权投资中常见的一种操作的手段,一般是在行情有大涨趋势的时候,投资者通过追加仓位来扩大收益和缩小持仓成本的策略&#xff0c;下文为大家介绍期权怎样的加仓才是合理的加仓&#xff1f;本文来自&#xff1a;期权酱 一、期权交易怎么加仓最合适&#xff1f;期…

[H5动画制作系列 ] Text及Button 的基础原理Demo

准备工作: 舞台上方是个动态文本框,名称为:myText,舞台下方是一个按钮元件(myButton)的实例,名称是:myButton1,当点击按钮时,能够在文本框上和控制台(console)输出:当前帧号以及全局i的变量值。建立两个图层,一个图层布局按钮和文本框,另一个图层专门部署代码。 操作步骤: 步…

WebGL 正确处理对象前后的关系——隐藏面消除(深度测试)/ 深度冲突

目录 前言 验证WebGL处理对象前后关系的规则——后绘制的图形覆盖先绘制的图形 隐藏面消除&#xff08;深度测试&#xff09; 开启隐藏面消除功能&#xff0c;需要遵循以下两步&#xff1a; 1.开启隐藏面消除功能。 gl.enable&#xff08;&#xff09;函数规范 2.在绘制…

计算机毕业设计 基于SSM的电影推荐系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…