vue3中实现el-tree通过ctrl或shift批量选择节点并高亮展示

news2024/11/17 11:56:40

一、看效果:

按住ctrl键实现单个多选                                按住shift实现区间范围多选                              

                  

二、代码:

        vue页面

<template>
  <el-tree
    class="w100%"
    :data="$.treeData"
    ref="treeTableListRef"
    :props="$.defaultProps"
    highlight-current
    :expand-on-click-node="false"
    key="id"
    :default-expand-all="true"
    @node-click="(data, node) => $.tableFieldsNodeClick(data, node, treeTableListRef)"
  >
    <template #default="{ data }">
      <div style="user-select: none">{{ data.name }}</div>
    </template>
  </el-tree>
</template>

<script setup lang="ts">
import { useData } from "./hooks/index";
const treeTableListRef = ref();
let { $data: $ } = useData();
onMounted(() => {});
onBeforeMount(() => {
  window.addEventListener("keydown", handleKeyDown);
  window.addEventListener("keyup", handleKeyUp);
});
// 按下为true
const handleKeyDown = (event: any) => {
  // 代表按下的是ctrl键
  if (event.key == "Control") {
    $.ctrlKeyPressed = true;
  }
  // 代表按下的是shift键
  if (event.key == "Shift") {
    $.shiftKeyPressed = true;
  }
};
// 释放为false
const handleKeyUp = (event: any) => {
  // 代表按下的是ctrl键
  if (event.key == "Control") {
    $.ctrlKeyPressed = false;
  }
  // 代表按下的是shift键
  if (event.key == "Shift") {
    $.shiftKeyPressed = false;
  }
};
</script>

<style scoped lang="scss">
</style>

        引入的hooks文件,index.ts

export function useData() {
    const $data: any = reactive({
        ctrlKeyPressed: false,
        shiftKeyPressed: false,
        shiftKeyFelid: [],
        defaultProps: {
            children: "children",
            label: "name",
        },
        treeData: [
            {
                name: '一级1',
                id: 1,
                children: [{
                    name: '二级1',
                    id: 2,
                    children: [{
                        name: '三级1',
                        id: 2,
                    }, {
                        name: '三级2',
                        id: 3,
                    }, {
                        name: '三级3',
                        id: 4,
                    }, {
                        name: '三级4',
                        id: 5,
                    }, {
                        name: '三级5',
                        id: 6,
                    }]
                }, {
                    name: '二级2',
                    id: 3,
                }, {
                    name: '二级3',
                    id: 4,
                }, {
                    name: '二级4',
                    id: 5,
                }, {
                    name: '二级5',
                    id: 6,
                }]
            }, {
                name: '一级2',
                id: 7,
                children: [{
                    name: '二级1',
                    id: 8,
                }, {
                    name: '二级2',
                    id: 9,
                }, {
                    name: '二级3',
                    id: 10,
                }, {
                    name: '二级4',
                    id: 11,
                }, {
                    name: '二级5',
                    id: 12,
                }]
            }],
        selectNodes: []
    })
    // 节点选中事件
    $data.tableFieldsNodeClick = (nodeData: any, node: any, treeTableListRef: any) => {
        const nodes = treeTableListRef.store._getAllNodes();//所有node节点
        const ishas = $data.selectNodes.includes(node.id)
        // 递归遍历节点数组进行ID存放
        function addSelectId(arr: any) {
            for (const item of arr) {
                $data.selectNodes.push(item.id)
                if (Array.isArray(item.children) && item.children.length) {
                    addSelectId(item.children)
                }
            }
        }
        // 递归遍历删除节点id
        function delSelectId(arr: any) {
            for (const item of arr) {
                const index = $data.selectNodes.findIndex((x: any) => x == item.id);
                $data.selectNodes.splice(index, 1);
                if (Array.isArray(item.children) && item.children.length) {
                    delSelectId(item.children);
                }
            }
        }
        // 按住了ctrl键,可以进行单个多选
        if ($data.ctrlKeyPressed) {
            // 如果为true代表当前选中的节点已存在
            if (ishas) {
                // 查找当前选中的节点的索引
                const index = $data.selectNodes.findIndex((x: any) => x == node.id);
                // 删除父节点
                $data.selectNodes.splice(index, 1);
                // 删除子节点
                if (Array.isArray(node.childNodes) && node.childNodes.length) {
                    deleteSelectId(node.childNodes);
                }
            } else {
                // 否则当前选中的节点不存在,就加入到已选节点数组序列
                $data.selectNodes.push(node.id)
                // 防止选中的是父节点,就需要递归将子节点加入
                if (Array.isArray(node.childNodes) && node.childNodes.length) {
                    addSelectId(node.childNodes);
                }
            }
            node.isCurrent = !node.isCurrent;
            // 按下了shift键,可以进行范围多选
        } else if ($data.shiftKeyPressed) {
            // 先清空
            $data.selectNodes = []
            // 将当前节点放入
            $data.selectNodes.push(node.id)
            $data.shiftKeyFelid.push(node.id);
            if ($data.shiftKeyFelid.length > 1) {
                // 首索引
                const sIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[0])
                // 尾索引
                const eIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[$data.shiftKeyFelid.length - 1]);
                // 根据首尾索引,存入中间节点
                const s = sIndex < eIndex ? sIndex : eIndex //取小值当开头索引
                const e = sIndex < eIndex ? eIndex : sIndex//取大值当结尾索引
                for (let i = s; i < e; i++) {
                    // 放入该区间节点id
                    $data.selectNodes.push(nodes[i].id);
                }
            }
        } else {
            // 否则就是单机选择
            $data.shiftKeyFelid = [];
            $data.selectNodes = [];
            $data.selectNodes = [node.id];
        }
        // 下面是对已选中的节点,进行高亮展示
        // 通过控制elementui中节点上的isCurrent属性
        // isCurrent为true是高亮,否则取消高亮
        for (const item of nodes) {
            if ($data.selectNodes.includes(item.id)) {
                item.isCurrent = true;
            } else {
                item.isCurrent = false;
            }
        }
    };
    return {
        $data: $data
    }
}

三、注意:

        1、重点是要获取当前所选节点数组

        2、通过循环节点数组来更新nodes节点中isCurrent属性,控制高亮

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

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

相关文章

2024年强烈推荐mac 读写NTFS工具Tuxera NTFS for Mac2023中文破解版

大家好啊&#xff5e;今天要给大家推荐的是 Tuxera NTFS for Mac2023中文破解版&#xff01; 小可爱们肯定知道&#xff0c;Mac系统一直以来都有一个小小的痛点&#xff0c;就是无法直接读写NTFS格式的移动硬盘和U盘。但是&#xff0c;有了Tuxera NTFS for Mac2023&#xff0c;…

扩散模型实战(十四):扩散模型生成音频

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 扩散模型实战&#xff08;四&#xff…

微软发布Orca2,“调教式”教会小规模大语言模型如何推理!

我们都知道在大多数情况下&#xff0c;语言模型的体量和其推理能力之间存在着正相关的关系&#xff1a;模型越大&#xff0c;其处理复杂任务的能力往往越强。 然而&#xff0c;这并不意味着小型模型就永远无法展现出色的推理性能。最近&#xff0c;奶茶发现了微软的Orca2公开了…

【工作生活】汽车电子嵌入式开发简介

目录 1. 目标 2. 要分享什么 3.1 行业知识 3.1.1车载行业知识&#xff1a; 3.1.2项目&#xff1a; 3.1.3开发测试工具&#xff1a; 3.2 硬件平台 3.3 基础知识 3.4 工作生活 3. 我们是谁 1. 目标 随着新能源汽车的快速崛起&#xff0c;汽车电子行业开始快速发展&…

记一次xss通杀挖掘历程

前言 前端时间&#xff0c;要开放一个端口&#xff0c;让我进行一次安全检测&#xff0c;发现的一个漏洞。 经过 访问之后发现是类似一个目录索引的端口。(这里上厚码了哈) 错误案例测试 乱输内容asdasffda之后看了一眼Burp的抓包&#xff0c;抓到的内容是可以发现这是一个…

GRE与顺丰圆通快递盒子

1. DNS污染 随想&#xff1a; 在输入一串网址后&#xff0c;会发生如下变化如果你在系统中配置了 Hosts 文件&#xff0c;那么电脑会先查询 Hosts 文件如果 Hosts 里面没有这个别名&#xff0c;就通过域名服务器查询域名服务器回应了&#xff0c;那么你的电脑就可以根据域名服…

15.Eclipse常用基本配置设置

在使用Eclipse进行Java开发之前&#xff0c;经常需要进行一些配置&#xff0c;其中有些配置甚至是必须的&#xff0c;即使开始不编辑之后开发过程中也会出一些因配置导致的小问题。本文梳理了一下Eclipse使用中常用的配置 1 编码配置 1.1 设置工作空间编码格式 打开Eclipse&…

第 7 部分 — 增强 LLM 安全性的策略:数学和伦理框架

一、说明 增强大型语言模型 (LLM) 安全性的追求是技术创新、道德考虑和实际应用的复杂相互作用。这项努力需要一种深入而富有洞察力的方法&#xff0c;将先进的数学模型与道德原则和谐地融合在一起&#xff0c;以确保LLM的发展不仅在技术上稳健&#xff0c;而且在道德上合理且对…

来自Sui的温馨建议:保护您的Web3私钥

当您安装一个钱包并创建Sui账户时&#xff0c;钱包包含一个公钥和一个私钥。保护好私钥的安全非常重要&#xff0c;从而可以保护您的Sui资产&#xff0c;包括钱包中的任何tokens。 公钥加密技术是几十年前开发的&#xff0c;是当今互联网上大多数安全交易的基础&#xff0c;包…

Python----多态

1、什么是多态 多态指的是一类事物有多种形态。 定义&#xff1a;多态是一种使用对象的方式&#xff0c;子类重写父类方法&#xff0c;调用不同子类对象的相同父类方法&#xff0c;可以产生不同的执行结果。 ① 多态依赖继承 ② 子类方法必须要重写父类方法 首先定义一个父类…

配电室无人值守改造

配电室无人值守改造是通过运用先进的技术和设备&#xff0c;将传统的需要人工值守的配电室改造成可以远程监控和管理的智能化配电室&#xff0c;从而实现无人值守。这种改造可以提高配电室的安全性、可靠性和效率&#xff0c;降低运维成本。 建立智能监控系统&#xff1a;通过安…

十二、MapReduce概述

1、MapReduce &#xff08;1&#xff09;采用框架 MapReduce是“分散——>汇总”模式的分布式计算框架&#xff0c;可供开发人员进行相应计算 &#xff08;2&#xff09;编程接口&#xff1a; ~Map ~Reduce 其中&#xff0c;Map功能接口提供了“分散”的功能&#xff…

spring boot 3.2 整合 keycloak

背景 项目中用到 keycloak&#xff0c;因此其他所有管理页面要集成 keycloak 做统一登录认证。 Keycloak 侧配置 容器方式启动 keycloak 服务端 docker run -d --name mykeycloak -p 8080:8080 -e KEYCLOAK_ADMINadmin -e KEYCLOAK_ADMIN_PASSWORDadmin ke…

Python ItsDangerous库:构建安全可靠的数据传输

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com ItsDangerous是Python中一个轻量级的库&#xff0c;旨在提供安全且简单的数据传输和签名功能。本文将深入介绍ItsDangerous的核心特性、基本用法以及在实际应用中的一些示例&#xff0c;通过丰富的示例代码&…

【思路代码详解】2023mathorcup大数据复赛B题妈妈杯高校数学建模挑战赛电商零售商家需求预测及库存优化问题

2023 年 MathorCup 高校数学建模挑战赛——大数据竞赛 赛道 B复赛&#xff1a;电商零售商家需求预测及库存优化问题 问题一 目标&#xff1a;制定补货计划&#xff0c;基于预测销量。 背景&#xff1a;固定库存盘点周期NRT1, 提前期LT3天。 初始条件&#xff1a;所有商品…

Qt12.8

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

线程池的使用及实现

使用多进程进行并发编程&#xff0c;会频繁的创建销毁进程&#xff0c;效率比较慢&#xff0c;所以引入了线程&#xff0c;线程使用复用资源的方式提高了创建销毁的效率&#xff0c;但是随着创建线程的频率进一步提高&#xff0c;开销仍然无法忽略不计了。 要想办法优化此处线…

防火墙是什么?聊聊部署Web应用防火墙的作用

数字经济时代&#xff0c;也是一个应用爆炸的时代。在享受应用带来的便利同时&#xff0c;当前却出现许多热点威胁&#xff0c;如供应链安全、零日漏洞、数据泄露等&#xff0c;都给现代化应用带来严峻挑战。有了WAF防火墙的帮助&#xff0c;就可以拦截一系列企图通过入侵系统来…

区块链如何影响数字营销的各个方面?

在过去的几年里&#xff0c;由于区块链等新技术和趋势的进步&#xff0c;数字营销领域发生了各种变化和发展。区块链是加密货币爱好者和投资者当前的流行语。然而&#xff0c;它的可能性已经超出了加密货币的世界&#xff0c;今天&#xff0c;来自不同行业的组织正在获得他们的…

目标检测器技术演进简史

引言 目标检测算法的发展已经取得了长足的进步&#xff0c;从早期的计算机视觉方法开始&#xff0c;通过深度学习达到了很高的准确度。在这篇博文中&#xff0c;我们将一起回顾一下这些算法的发展阶段以及现代目标检测系统中使用的主要方法。 我们首先回顾早期传统的目标检测…