element-ui Tree 树形控件 过滤保留子级并获取过滤后的数据 多选改单选

本示例基于vue2 + element-ui

element-ui 的官网demo是只保留到过滤值一级的,并不会保留其子级

目标

1、Tree 树形控件 保留过滤值的子级

2、在第一次过滤数据的基础上进行第二次过滤

3、Tree 树形控件 多选改为单选,且只有最末端子级可以选择

不足之处

过滤时无法指定过滤哪一级的数据(保留其子级数据)

实际场景需求

  1. 第一次过滤时只过滤第三级数据
  2. 第二次过滤时在第一次过滤的基础上过滤最后一级

1 暂时无法实现(如果有大佬用前端方法实现,记得call我!)

2 过滤最后一级可以实现(代码随后附上)

先看效果

1、2

3  多选改单选效果

Tree 树形控件 保留过滤值的子级

<el-tree
  class="filter-tree"
  node-key="id"
  :data="treeData"
  :props="defaultProps"
  default-expand-all
  show-checkbox
  @check-change="handleCheckChange"
  :filter-node-method="filterNode"
  ref="tree">
</el-tree>


// 对树节点进行筛选时执行的方法
filterNode (value, data, node) {
  let parentNode = node.parent; // 父级node
  let labels = [node.label]; // 当前node的名字
  let level = 1; // 层级
  while (level < node.level) {
    labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
    parentNode = parentNode.parent;
    level++;
  }
  return labels.some((d) => d.indexOf(value) !== -1);
},

在第一次过滤数据的基础上进行第二次过滤

1、下载插件库

npm install -S circular-json

2、在使用页面引入

import CircularJSON from 'circular-json'

3、代码应用

<template>
  <div class="about-container">
    <h1>获取过滤后的tree数据</h1>
    <el-input
      clearable
      placeholder="第一次过滤"
      @keyup.enter.native="handleFilter1"
      v-model="firstText">
    </el-input>
    <el-input
      style="margin-top: 10px;"
      clearable
      placeholder="第二次过滤"
      @keyup.enter.native="handleFilter2"
      v-model="secondText">
    </el-input>
    <el-button @click="handleFilter1(),handleFilter2()" type="primary" icon="el-icon-search">搜索</el-button>
    <div>
      <el-tree
        class="filter-tree"
        node-key="id"
        :data="treeData"
        :props="defaultProps"
        default-expand-all
        show-checkbox
        @check-change="handleCheckChange"
        :filter-node-method="filterNode"
        ref="tree">
      </el-tree>
    </div>
  </div>
</template>

<script>
  // 在使用的组件内引入
  import CircularJSON from 'circular-json'

  export default {
    data() {
      return {
        // 第一次过滤
        firstText: '',
        // 第二次过滤
        secondText:'',
        // tree控件的渲染值
        treeData: [{
          id: 1,
          label: '一级1',
          children: [{
            id: 4,
            label: '二级1-1',
            children: [{
              id: 9,
              label: '三级1-1-1',
              children: [{
                id:91,
                label: '四级1'
              },{
                  id:92,
                  label: '四级2'
              }]
            }, {
              id: 10,
              label: '三级1-1-2'
            }]
          }]
        }, {
          id: 2,
          label: '一级2',
          children: [{
            id: 5,
            label: '二级2-1'
          }, {
            id: 6,
            label: '二级2-2'
          }]
        }, {
          id: 3,
          label: '一级',
          children: [{
            id: 7,
            label: '二级3-1'
          }, {
            id: 8,
            label: '二级3-2'
          },{
            id: 82,
            label: '四级3'
          }]
        },{
          id: 31,
          label: '奇迹',
          children: [{
            id: 71,
            label: '奇迹1'
          }, {
            id: 81,
            label: '奇迹2'
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'label'
        },
        // tree的原版备份数据
        deepCloneTreeData:[],
        // 第一次过滤后tree控件渲染数据
        firstFilterdata:[],
      }
    },
    mounted() {
      this.deepClone(this.treeData).then((res)=>{
        this.deepCloneTreeData = res;
      })
    },
    methods: {
      // 第一次过滤
      handleFilter1() {
        // 第一次过滤时没有输入值,即用tree控件的原始值
        if(!this.firstText){
          this.treeData = this.deepCloneTreeData;
          this.firstFilterdata = this.deepCloneTreeData;
          return
        }
        this.$refs.tree.filter(this.firstText)
        this.firstFilterdata = this.getFilterData();
      },
      // 第二次过滤
      handleFilter2() {
        // 基于第一次过滤出来的数据
        if(this.firstFilterdata.length > 0) this.treeData = this.firstFilterdata;
        this.$nextTick(()=>{
          this.$refs.tree.filter(this.secondText);
        })
      },
      // 对树节点进行筛选时执行的方法
      filterNode (value, data, node) {
        let parentNode = node.parent; // 父级node
        let labels = [node.label]; // 当前node的名字
        let level = 1; // 层级
        while (level < node.level) {
          labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
          parentNode = parentNode.parent;
          level++;
        }
        return labels.some((d) => d.indexOf(value) !== -1);
      },
      // tree 的选择事件
      handleCheckChange(data, checked, indeterminate) {
        const arr = this.$refs.tree.getCheckedKeys()
      },
      // 需要获取过滤后的 Tree组件数据
      getFilterData() {
          const rootData = this.$refs.tree.root;
          if (rootData.visible) {
            const childNodesStr = CircularJSON.stringify(rootData.childNodes);
            const childNodes = CircularJSON.parse(childNodesStr);
            const filterData = this.recursionNodes(childNodes);
            return filterData;
        }
      },
      /**
       * 递归遍历数据
       * 这里解释一下为什么要用CircularJSON这个插件,因为element tree
       * node数据存在一个对象里的子项存在循环引用,存在循环引用的对象
       */
      recursionNodes(childNodes) {
        const nodes = childNodes;
        const result = [];
        for (const item of nodes) {
          if (item.visible) {
            result.push(item.data);
          }
          if (item.childNodes && item.childNodes.length) {
            const tempResult = this.recursionNodes(item.childNodes);
            item.data.children = tempResult;
          }
        }
        return result;
      },
      /**
       * 深拷贝
       */
      deepClone(obj){
          return new Promise((resolve) => {
              const { port1,port2 } = new MessageChannel();
              port1.postMessage(obj);
              port2.onmessage = (msg) => {
                  resolve(msg.data)
              }
          })
      }
    },
  }
</script>

只过滤最后一级

/** 
 * 数据处理
 * 
 * 需要对每级数据进行level标记,方便后续过滤
 */
treeData: [{
  id: 1,
  label: '一级1',
  level:1,
  children: [{
    id: 4,
    label: '二级1-1',
    level:2,
    children: [{
      id: 9,
      label: '三级1-1-1',
      level:3,
      children: [{
        id:91,
        label: '四级1',
        level:4,
      },{
          id:92,
          label: '四级2',
          level:4,
      }]
    }, {
      id: 10,
      label: '三级1-1-2',
      level:3,
    }]
  }]
}, {
  id: 2,
  label: '一级2',
  level:1,
  children: [{
    id: 5,
    label: '二级2-1',
    level:2,
  }, {
    id: 6,
    label: '二级2-2',
    level:2,
  }]
}, {
  id: 3,
  label: '一级',
  level:1,
  children: [{
    id: 7,
    label: '二级3-1',
    level:2,
  }, {
    id: 8,
    label: '二级3-2',
    level:2,
  },{
    id: 82,
    label: '四级3',
    level:2,
  }]
},{
  id: 31,
  label: '奇迹',
  level:1,
  children: [{
    id: 71,
    label: '奇迹1',
    level:2,
  }, {
    id: 81,
    label: '奇迹2',
    level:2,
  }]
}]


// 对树节点进行筛选时执行的方法
filterNode(value, data, node) {
  /**
   * 筛选最后一级可用
   * 
   * [4].includes(data.level
   * [] 中写入最后一级的level值
   */
  if ([4].includes(data.level) && data.label.indexOf(value) !== -1) {
    console.log(value,data,node,'4-------',data.label.indexOf(value));
    let parentNode = node.parent; // 父级node
    let labels = [node.label]; // 当前node的名字
    let level = 1; // 层级
    while (level < node.level) {
      // console.log(labels,'labels');
      labels = [...labels, parentNode.label]; // 当前node名字,父级node的名字
      parentNode = parentNode.parent;
      level++;
    }
    return labels.some((d) => d.indexOf(value) !== -1);
  }
},

Element tree组件 多选改为单选

<el-tree
  class="treeRadio"
  check-strictly
  @check-change="deptCheck"

deptCheck(data, check, childCheck) {
  if(check){
    this.$refs.tree.setCheckedNodes([data]);
  }
}

// css 让父级不显示checkbox
::v-deep .el-tree .el-tree-node .is-leaf + .el-checkbox .el-checkbox__inner{
  display: inline-block;
}
::v-deep .el-tree .el-tree-node .el-checkbox .el-checkbox__inner{
  display: none;
}
::v-deep .treeRadio .el-checkbox__inner{
  border-radius: 50%;
  transform: scale(1.2);
}
// 样式改为单选框的样式
::v-deep .treeRadio .el-checkbox__inner{
  border-radius: 50%;
  transform: scale(1.2);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring】AOP的AspectJ开发

AOP基础不了解可以阅读&#xff1a;【Spring】AOP原来如此-CSDN博客 AspectJ是一个居于JAVA开发的AOP框架 基于XML的声明式AspectJ 基于XML的声明式AspectJ是通过XML文件来定义切面&#xff0c;切入点及通知&#xff0c;所有的切面、切入点和通知必须定义在内&#xff0c; 元…

Android Jetpack学习系列——Navigation

写在前面 Google在2018年就推出了Jetpack组件库&#xff0c;但是直到今天我才给重视起来&#xff0c;这真的不得不说是一件让人遗憾的事。过去几年的空闲时间里&#xff0c;我一直在尝试做一套自己的组件库&#xff0c;帮助自己快速开发&#xff0c;虽然也听说过Jetpack&#…

第一课:Transformer

第一课&#xff1a;Transformer 文章目录 第一课&#xff1a;Transformer1、学习总结&#xff1a;什么是语言模型&#xff1f;大语言模型&#xff08;LLM&#xff09;技术演变史注意力机制Transformer结构课程ppt及代码地址 2、学习心得&#xff1a;3、经验分享&#xff1a;4、…

【DevOps-02】Code编码阶段工具

一、简要说明 在code阶段,我们需要将不同版本的代码存储到一个仓库中,常见的版本控制工具就是SVN或者Git,这里我们采用Git作为版本控制工具,GitLab作为远程仓库。 Git安装安装GitLab配置GitLab登录账户二、Git安装 Git官网 Githttps://git-scm.com/

移动通信原理与关键技术学习(2)

1.多径信道滤波器表示&#xff0c;多径信道可以认为是线性时变滤波器&#xff0c;接收信号为发送信号与信道冲激响应的卷积。 2.调制就是对信号源的信息进行处理加到载波上&#xff0c;使其变为适合于信道传输的形式的过程&#xff0c;就是使载波随信号而改变的技术。 3.进行调…

VUE 若依框架,当页面设置了keepAlive=true,v-if和v-hasPermi作用在统一个按钮上时v-hasPermi失效,出现按钮显示异常问题

当前列表页设置了缓存keepAlivetrue&#xff0c;同时&#xff0c;在同一个按钮上使用v-if判断数据状态、用v-hasPermi判断按钮权限 当v-if的数据状态改变&#xff0c;由 1 变成 2 的时候&#xff0c;后面的v-hasPermi判断失效 原因&#xff1a; 是因为一开始页面初始化时&#…

HTML5+CSS3⑥——CSS三大特性、表格、列表

CSS特性 继承性 层叠性 优先级 叠加计算规则 表格 表格结构标签 合并单元格 列表 无序列表 有序列表 定义列表

显著提升VMware虚拟机运行速度的技巧

最主要是要把CPU核心减少到2&#xff0c;以前设置为4非常卡。因为我的电脑一个就4个CPU。

听GPT 讲Rust源代码--compiler(11)

File: rust/compiler/rustc_mir_transform/src/simplify.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_mir_transform/src/simplify.rs文件是Rust编译器中一系列进行MIR&#xff08;中间表示&#xff09;简化的转换的实现。MIR是Rust编译器中用于进行优化和代码生成的中间…

Python遍历读取 A 文件夹中的 A1、A2、A3、A4、A5 中的各子文件夹中的图片,并对每张图片处理后保存到指定路径

目录 一、具体步骤二、文件夹目录结构样例三、代码四、实例遍历处理后结果五、总结 一、具体步骤 首先&#xff0c;指定 A 文件夹的路径和重命名后的文件夹路径。 然后&#xff0c;遍历 A 文件夹中的各子文件夹。 在每个子文件夹中&#xff0c;遍历所有文件。 读取每个文件&am…

电路分析竟然这么简单?还可以用软件仿真~

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…

【MongoDB】关于MongoDB更新文档update的操作,十分详细,建议收藏!!!

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;MongoDB数据库学习 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继…

UDP单播

CMakeLists.txt文件中添加如下行&#xff1a; link_libraries(ws2_32) 1.发送端 #include <iostream> #include <winsock2.h> #include <cstdio>#pragma comment(lib, "Ws2_32.lib") // Link with ws2_32.libint main() {1.Initialize winsock…

googlecode.log4jdbc慢sql日志,格式化sql

前言 无论使用原生JDBC、mybatis还是hibernate&#xff0c;使用log4j等日志框架可以看到生成的SQL&#xff0c;但是占位符和参数总是分开打印的&#xff0c;不便于分析&#xff0c;显示如下的效果: googlecode Log4jdbc 是一个开源 SQL 日志组件&#xff0c;它使用代理模式实…

AI的突破与融合:2024年中国智能技术的新纪元_光点科技

随着人工智能领域的不断突破&#xff0c;2024年注定将成为中国智能技术发展的一个新纪元。当下&#xff0c;AI技术不仅在理论研究上取得了重大进展&#xff0c;其在商业应用、社会服务等领域的融合也日益深入。本文将结合近期网络上的AI热点&#xff0c;展望中国在AI技术方面的…

Springboot整合RocketMQ 基本消息处理

目录 1. 同步消息 2. 异步消息 3. 单向消息 4. 延迟消息 5. 批量消息 6. 顺序消息 7. Tag过滤 导入依赖 <dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId></dependency> …

CNN——AlexNet

1.AlexNet概述 论文原文&#xff1a;ImageNet Classification with Deep Convolutional Neural Networks 在LeNet提出后&#xff0c;卷积神经网络在计算机视觉和机器学习领域中很有名气。但卷积神经网络并没有主导这些领域。这是因为虽然LeNet在小数据集上取得了很好的效果&am…

保姆级教程:从0到1搭建web自动化测试环境

之前都是在linux上安装&#xff0c;第一次在windows上配置环境&#xff0c;加上距离上次配置环境有点久了&#xff0c;竟也花了点时间。特此记录下保姆级教程&#xff0c;给初学者一个有效的参考&#xff01; 一. 环境搭建 工具清单 工具工具名版本Java开发工具包JDK1.8浏览…

AI边缘计算智能分析网关V4如何配置周界入侵检测算法

旭帆科技的智能分析网关V4内含近40种智能分析算法&#xff0c;包括人体、车辆、消防、环境卫生、异常检测等等&#xff0c;在消防安全、生产安全、行为检测等场景应用十分广泛&#xff0c;如常见的智慧工地、智慧校园、智慧景区、智慧城管等等&#xff0c;还支持抓拍、记录、告…

C++第四天

定义一个Person类&#xff0c;私有成员int age&#xff0c;string &name&#xff0c;定义一个Stu类&#xff0c;包含私有成员double *score&#xff0c;写出两个类的构造函数、析构函数、拷贝构造和拷贝赋值函数&#xff0c;完成对Person的运算符重载(算术运算符、条件运算…