element-plus elplus el-tree三种图标自定义 并且点击图标展开收起 点击文字获取数据

2023-11-01

前言
公司需求,需要实现如下样式的树形列表 (基于vue3 + element-plus)
在这里插入图片描述
当节点展开时,显示展开的文件夹图标,当节点收起时显示收起的文件夹,最后一级显示文件样式
废话没有了, 代码如下

<!-- 树形列表组件 -->
<template>
  <div class="tree-input" v-if="filter">
    <el-input v-model="filterText" clearable placeholder="输入关键字" />
  </div>
  <el-tree :data="treeDataList" highlight-current :node-key="nodeKey"
   :current-node-key="currentNodekey" :default-expanded-keys="defaultExpandedList"
  ref="treeRef" icon="none" :filter-node-method="fliterNode" :expand-on-click-node="false" >
    <template #default="{ data }">
      <div class="com-tree">
        <el-icon size="13" class="com-tree-icon" @click="toggleChild(data)" >
          <Document v-if="data.isLast" />
          <FolderOpened v-else-if="data.opened" />
          <Folder v-else />
        </el-icon>
        <div class="com-tree-text" @click="handleNodeClick(data)" >{{ data[prop.label] }}</div>
      </div>
    </template>
  </el-tree>
</template>

<script setup>
import { Folder, FolderOpened, Document } from "@element-plus/icons-vue"
import { compileTreeData } from '@/utils/compileTreeData.js'

const props = defineProps({
  // 树内容
  treeData: {
    type: Array,
    default: []
  },
  // 过滤器
  filter: {
    type: Boolean,
    default: false
  },
  // 树形结构属性绑定值
  prop: {
    type: Object,
    default: {
      label: 'label'
    }
  },
  // 树节点唯一绑定值 注意是唯一值 不是value值
  nodeKey: {
    type: String,
    default: 'id'
  },
  // 当前选中的树节点 即nodeKey
  currentNodekey: {
    type: [String, Number],
    default: ''
  },
  // 默认展开的树节点列表  即nodeKey组成的列表
  defaultExpandedList: {
    type: Array,
    default: []
  },
})


// 树dom
const treeRef = ref()
const treeDataList = ref([])

// 当有默认展开时,切换展开图标样式
const expandIcon = () => {
  treeDataList.value.map(item => {
    if (props.defaultExpandedList.includes(item[props.nodeKey])) {
      item.opened = true
    }
  })
}

// 监听传入的树形结构, 并且进行转化
watch(() => props.treeData, newValue => {
  if (newValue.length > 0) {
    const treeDataTemp = [...newValue]
    // 获得新的树形结构
    treeDataList.value = compileTreeData(treeDataTemp)

    // 如果传入了默认展开
    if (props.defaultExpandedList.length > 0) {
      expandIcon() // 切换展开图标样式
    }
  }
}, {
  immediate: true
})

const emits = defineEmits(['node-click'])

// 点击图标
const toggleChild = (data) => {
  let nodes = treeRef.value.store.nodesMap
  // console.log('nodes', nodes)
  for (let i in nodes) {
    const item = nodes[i]
    if (item.data[props.nodeKey] === data[props.nodeKey] && !item.data.isLast) {
      data.opened = !data.opened // 图标切换
      item.expanded = data.opened // 展开或收起子节点
    }
  }
}

const handleNodeClick = (data) => {
  emits('node-click', data)
}


// 树过滤文本 
const filterText = ref('')
watch(filterText, (val) => {
  treeRef.value.filter(val)
})
// 树过滤
const fliterNode = (value, data) => {
  if (!value) return true
  return data.label.includes(value)
}
// 折叠全部节点
const setAllFold = () => {
  let nodes = treeRef.value.store.nodesMap;
    for (const node in nodes) {
      nodes[node].expanded = false;
    }
}


// 清除输入框 折叠所有节点
const clearInput = () => {
  filterText.value = ''
  setAllFold() // 折叠所有节点
}

defineExpose({
  clearInput
})
</script>

<style lang="scss" scoped>
.tree-input {
  padding: 0 24px 10px;
}
.com-tree {
  display: flex;
  align-items: center;
  &-icon {
    margin-right: 10px;
    flex: 0 0 auto;
  }
  &-text {
    flex: 1;
  }
}
</style>

用到的JS

compileTreeData.js

let topId = '' // 最高级ID 考虑到点击很底层需要用到最高层id 而后端没有返回
const deepLoop = (treeData, isChild) => { // 一个递归
  if (treeData && Array.isArray(treeData)) {
    treeData.map(item => {
      if (!isChild) { // 进入if 表示当前item为顶级
        topId = item.id
      }
      item.opened = false // 默认全部都是收起状态
      item.topId = topId // 不是顶级的 赋值顶级ID 
      if (item.children && item.children.length > 0) { // 有子元素
        item.isLast = false // 不是最后一级
        deepLoop(item.children, true) // 进行递归
      }else { // 是最后一级
        item.isLast = true 
      }
    })
    return treeData
  }
}


export const compileTreeData = (treeData)=> {
  return deepLoop(treeData)
}

还有一件事

有的时候文字很短,不好点击,需要点击文字右侧空白也能触发数据回传事件
那么你需要想办法 覆盖这个类 ---- .el-tree-node__label
覆盖后即可

/* 我的写法 */
.my-app .el-tree-node__label {
  flex: 1;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

element-plus elplus el-tree三种图标自定义 并且点击图标展开收起 点击文字获取数据 的相关文章

随机推荐

  • Got minus one from a read call错误解决办法

    在我使用Oracle自带的工具sqldevloper Oracle10 11都带个工具 用起来还行 就是有点慢 登录服务器Oracle9i数据库的时候 出现了这个提示 网上一查 很多人是在执行JAVA程序的时候报了这个异常 好心人给出的明确
  • 华为社招面试笔试

    1 机试题 机试有两道题 一道题200分 120分及格 题目一 给你一个正整数n 假设有两个质数加起来等于n 问一共有多少组这样的质数 题目二 字符串匹配 给你一个父串 一个子串 求父串中子串出现的次数 温馨提示 机试题其实用暴力破解就可以
  • 使用百度地图接口实现自定义网页地图开发实现

    上午研究了下一些网站都已经实现好的地区 公交 线路等等一些基于 地图 的服务 这些服务都是基于诸如百度 谷歌地图服务接口下的二次开发 百度地图接口服务免费 而且开发文档 API介绍详细 所以本文暂先介绍如何调用百度地图服务 API http
  • java中四大作用域

    Java的四大作用域为 PageContext ServletRequest HttpSession ServletContext 下面一起了解一下Java的四大作用域吧 首先按照作用范围来算 是PageContext jsp页面
  • 路由器从外向内访问(端口转发)及从内向外访问(NAT)的配置

    路由器从外向内访问 端口转发 及从内向外访问 NAT 的配置 描述需求 最近工作上有一个需求 大致意思就是解决路由器内外访问的问题 这个问题可以分成两部分 一个是外部设备 如服务器 能主动访问路由器局域网内的主机 另一个就是内部的主机需要能
  • Java基础-反射

    反射的基本作用 关键 反射是在运行时获取类的字节码文件对象 然后可以解析类中的全部成分 反射的核心思想和关键就是 得到编译后的字节码 class 文件对象 反射的第一步 获取Class类对象 如此才可以解析类的全部成分 获取Class类的对
  • (四)PointPillars论文的MMDetection3D代码解读——网络结构篇

    四 PointPillars论文的MMDetection3D代码解读 网络结构篇 PointPillars 是一个来自工业界的模型 整体的思想是基于图片的处理框架 直接将点云从俯视图的视角划分为一个个的立方柱体 Pillars 从而构成了伪
  • php no route to host,解决 重启后zerotier无法远程连接,显示”no route to host”

    解决 重启后zerotier无法远程连接 显示 no route to host 第一步 禁用桌面环境 桌面环境重启时经常会无原无故卡住 导致远程连不上 systemctl set default graphical target 第二步
  • ubuntu 20.04 安装make_ext4fs

    制作文件系统发现 sudo make ext4fs command not found 解决方法 sudo apt install android sdk ext4 utils sudo apt install e2fsprogs sudo
  • 使用纯C语言定义通用型数据结构的方法和示例

    文章目录 前言 以实现优先队列来描述实现思想 基本类型的包装类型 比较函数 演示 总结 前言 最近一段时间在复习数据结构和算法 用的C语言 不得不说 不学个高级语言再回头看C语言根本不知道C语言的强大和完美 不过相比之下也有许多不便利的地方
  • 历时30个小时 更新到了25905.1000 版本 23H2

  • 【Vue3】之vuex的安装与配置

    安装 yarn add vuex 4 或 npm install save vuex 4 创建 新建store js store js import createStore from vuex export default createSt
  • Pyinstaller 使用说明

    安装 cmd pip install pyinstaller 也可以自己下载安装包 解压后通过执行python setup py install 使用 pyinstaller F myPython py 或者用python pyinstal
  • 用IDEA创建第一个SpringBoot程序,并开发一个JSON接口

    1 打开idea主界面选择 Create New Project 2 在弹出的页面中我们选择左侧的 Spring Initializr jdk版本选择自己安装的版本 PS jdk版本要1 8以上哦 3 下一个页面 在Group栏输入组织名
  • IDEA代码覆盖率测试

    代码覆盖率测试 1 使用idea自带的代码覆盖率工具 1 创建test文档 右击将 test 目录设置为测试文档 2 选中需要测试的类 按Ctrl shift T 创建测试类 并选中要测试的方法 在测试案例中 编写测试代码 点击Edit C
  • 小程序分包实现

    目录 一 使用场景 二 操作方式 1 建立分包文件夹 2 文件构建 3 文件配置 三 总结 一 使用场景 微小程序分包常用于代码量较大的小程序 发布时会受到大小限制 二 操作方式 1 建立分包文件夹 在项目根目录下创建分包文件夹 此处我创建
  • L1-8 乘法口诀数列

    本题要求你从任意给定的两个 1 位数字 a1 和 a2 开始 用乘法口诀生成一个数列 an 规则为从 a1 开始顺次进行 每次将当前数字与后面一个数字相乘 将结果贴在数列末尾 如果结果不是 1 位数 则其每一位都应成为数列的一项 输入格式
  • ad电阻原理图_光敏电阻的基础知识介绍

    39G电子技术 电路 电子元件等 全套资料免费领 干货下载 十天学会单片机完整版 100个实例 PPT 点击上方红字 即可获取 一 光敏电阻 光敏电阻是用硫化隔或硒化隔等半导体材料制成的特殊电阻器 表面还涂有防潮树脂 具有光电导效应 二 特
  • TCP 拥塞窗口原理

    学过网络相关课程的 都知道TCP中 有两个窗口 滑动窗口 在我们的上一篇文章中有讲 接收方通过通告发送方自己的可以接受缓冲区大小 这个字段越大说明网络吞吐量越高 从而控制发送方的发送速度 拥塞窗口 也就是本文要讲的 概念 一个连接的TCP双
  • element-plus elplus el-tree三种图标自定义 并且点击图标展开收起 点击文字获取数据

    前言 公司需求 需要实现如下样式的树形列表 基于vue3 element plus 当节点展开时 显示展开的文件夹图标 当节点收起时显示收起的文件夹 最后一级显示文件样式 废话没有了 代码如下