Element UI-Select选择器结合树形控件终极版

Element UI Select选择器控件结合树形控件实现单选和多选,并且通过v-model的方式实现节点的双向绑定,封装成vue组件,文件名为electricity-meter-tree.vue,其代码如下:

<template>
  <div>
    <el-select
        :value="selectedId"
        :multiple="multiple"
        placeholder="请选择"
        ref="selectTree"
        clearable
        @change="handleChange"
        @clear="handleClear">
      <el-option v-for="form in hiddenForm" :key="form.id" :value="form.id" :label="form.label" hidden/>
      <div style="padding: 10px 14px">
        <el-input placeholder="输入关键字进行过滤" v-model="filterText" clearable>
          <template #suffix>
            <el-button type="text" icon="el-icon-search" style="max-width: 22px">
              <i class="el-icon-search" style="display: none;"></i>
            </el-button>
          </template>
        </el-input>
        <el-tree
            v-loading="loading"
            :data="treeData"
            ref="tree"
            :props="defaultProps"
            node-key="id"
            accordion
            default-expand-all
            :filter-node-method="filterNode"
            :show-checkbox="multiple"
            :check-strictly="checkStrictly"
            :highlight-current="highLightCurrent"
            @check-change="handleCheckChange"
            @node-click="handleNodeClick">
            <!-- 来源于省的电表以蓝色底标识。-->
             <template v-slot="{ node, data }">
               <span v-if="data.sources === 'province'" style="background: #1890ff;color: #FFFFFF;padding: 2px;">
                 {{ node.label}}
               </span>
               <span v-else>{{ node.label}}</span>
            </template>
        </el-tree>
      </div>
    </el-select>
  </div>
</template>

<script>

export default {
  model: {
    prop: 'value',
    event: 'change'
  },
  props: {
    value: {
      type: [Object, Array], // 根据实际情况选择类型
      default: () => {} // 格式:{id: 'xx', label: 'xx'}或者[{id: 'xx', label: 'xx'}]
    },
    multiple: { // 是否多选
      type: Boolean,
      default: false
    },
    checkStrictly: { // 父子是否不互相关联
      type: Boolean,
      default: false
    },
  },
  watch: {
    value: {
      handler (val) {
        if (this.multiple) {
          if (val && val.length > 0) {
            this.hiddenForm = val;
            this.selected = val;
          }else {
            this.hiddenForm = [{id: '', label: ''}];
            this.selected = [];
          }
        } else {
          if (val) {
            this.selected = val;
            this.hiddenForm = [val];
          }else {
            this.hiddenForm = [{id: '', label: ''}];
            this.selected = null;
          }
        }
      },
      immediate: true,
      deep: true
    },
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },
  computed: {
    selectedId () {
      if (this.multiple) {
        return this.selected && this.selected.length > 0 ? this.selected.map(item => item.id) : [];
      }
      return this.selected? this.selected.id : '';
    },
  },
  data () {
    return {
      filterText: '',
      treeData: [],
      defaultProps: {
        children: 'children',
        label: 'label',
        id: 'id',
        disabled: 'disabled'
      },
      selected: [],// 格式:{} 或者 []
      hiddenForm: [
        {
          id: '',
          label: ''
        },
      ],
      highLightCurrent: true,
      loading: false,
    }
  },
  methods: {
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    handleCheckChange (data, checked) {
      if (this.multiple) { // 多选
        const nodes = this.$refs.tree.getCheckedNodes();
        this.hiddenForm = nodes.length > 0 ? nodes : [{id: '', label: ''}];
        // 保证重现加载数据时,已选中的数据不被清除
        if (checked) {
          if (!this.selected || this.selected.length === 0) {
            this.selected = nodes;
          }else {
            // 定义一个函数来去重
            function removeDuplicates(array, uniqueKey) {
              let seen = new Map(); // 使用 Map 来存储已见过的 id 和对应对象
              // 遍历数组中的每个对象
              for (let obj of array) {
                // 如果 Map 中还没有这个 id,就添加进去
                if (!seen.has(obj[uniqueKey])) {
                  seen.set(obj[uniqueKey], obj); // 使用 id 作为 key,对象作为 value
                }
              }
              // 从 Map 中提取所有对象组成新的数组返回
              return Array.from(seen.values());
            }
            this.selected = removeDuplicates([...this.selected, ...nodes], 'id');
          }
        }else {
          this.selected = this.selected?.filter(item => item.id !== data.id);
        }
        this.$emit('change', this.selected);
      } else {}
    },
    handleNodeClick (data, node) {
      if (data.disabled) return;
      if (this.multiple) {} else { // 单选
        this.hiddenForm = [
          {
            id: data.id,
            label: data.label
          }
        ]
        this.selected = data;
        this.$emit('change', data);
        // 使 input 失去焦点,并隐藏下拉框
        // node.isLeaf && this.$refs.selectTree.blur();
      }
    },
    handleChange (value) {
      if (!value) return;
      this.selected = this.selected?.filter(item => value.includes(item.id));
      this.$emit('change', this.selected);
      this.multiple && this.$refs.tree.setCheckedKeys(this.selectedId);
    },
    handleClear () {
      this.selected = [];
      this.multiple && this.$refs.tree.setCheckedKeys([]);
      this.hiddenForm = [
        {
          id: '',
          label: ''
        }
      ];
      this.highLightCurrent = false;
      this.$emit('change', this.multiple ? [] : null);
    },
    getTreeDataAsync() {
      // 这里模拟调用后端接口返回的数据
      this.treeData = [
        {
          id: '1',
          label: 'XX市智能电表',
          children: [
            {
              id: '1-1',
              label: '通用智能电表A',
              children: [
                {
                  id: '1-1-1',
                  label: '通用智能电表B',
                  sources: 'province',
                },
                {
                  id: '1-1-2',
                  label: '通用智能电表C',
                },
              ]
            },
            {
              id: '1-2',
              label: '智能电表01',
              children: [
                {
                  id: '1-2-1',
                  label: '智能电表02',
                  sources: 'province',
                }
              ]
            },
          ]
        }
      ];
    }
  },
  created() {
    this.getTreeDataAsync();
  },
}
</script>

<style scoped>
</style>

该组件的用法如下:

 <electricity-meter-tree v-model="electricityMeter" multiple checkStrictly @change="electricityMeterChange"/>
  1. 引入组件:electricity-meter-tree
  2. 如果multiple为true多选时,那么electricityMeter的结构为[{id: ‘xx’, label: ‘xx’}],如果 mutilple为false单选时,那么electricityMeter的结构为{id: ‘xx’, label: ‘xx’}
  3. checkStrictly是否父子不互相关联,前提是multiple为true
  4. change事件也可以获取选中的节点

效果如下:
在这里插入图片描述

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

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

相关文章

9.RabbitMQ消息的可靠性

九、消息的可靠性 1、生产者确认 9.1.1、Confirm模式简介 可能因为网络或者Broker的问题导致①失败,而此时应该让生产者知道消息是否正确发送到了Broker的exchange中&#xff1b; 有两种解决方案&#xff1a; 第一种是开启Confirm(确认)模式&#xff1b;(异步) 第二种是开…

探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(二)

文章目录 2.3.3 极化编码巴氏参数与信道可靠性比特混合生成矩阵编码举例 2.3.4 极化译码最小单元译码串行抵消译码&#xff08;SC译码&#xff09;算法SCL译码算法 2.3.5 总结**Polar 码的优势****Polar 码的主要问题****Polar 码的应用前景** 2.3.6 **参考文档** 本博客为系列…

【我的 PWN 学习手札】House of Emma

House of Emma 参考文献 第七届“湖湘杯” House _OF _Emma | 设计思路与解析-安全KER - 安全资讯平台 文章 - house of emma 心得体会 - 先知社区 前一篇博客【我的 PWN 学习手札】House of Kiwi-CSDN博客的利用手法有两个关键点&#xff0c;其一是利用__malloc_assert进入…

【单片机通信技术】STM32 HAL库 SPI主从机通过串口发送数据

一、说明 使用STM32F103C8T6最小系统板&#xff0c;让板载SPI1与SPI2通信&#xff0c;通过串口收发数据。本文章说明了在配置与编写时遇到的一些问题&#xff0c;以及详细说明如何使用cubeMAX进行代码编写。 二、CubeMAX配置 1.时钟配置选择外部高速时钟 2.系统模式与时钟配…

IDEA 使用codeGPT+deepseek

一、环境准备 1、IDEA 版本要求 安装之前确保 IDEA 处于 2023.x 及以上的较新版本。 2、Python 环境 安装 Python 3.8 或更高版本 为了确保 DeepSeek 助手能够顺利运行&#xff0c;您需要在操作系统中预先配置 Python 环境。具体来说&#xff0c;您需要安装 Python 3.8 或更高…

Vue 3 实现富文本内容导出 Word 文档:前端直出方案与优化实践

本文将深入讲解如何通过纯前端方案将富文本内容直接导出为符合中文排版规范的 Word 文档&#xff0c;对比传统服务端生成方案&#xff0c;本方案可降低服务器压力 80% 以上&#xff0c;同时支持即时下载功能。 一、功能全景图 该方案实现以下核心能力&#xff1a; ✅ 纯前端 W…

数据可视化设计-FineBI

数据可视化设计-FineBI 5.1 FineBI概述 5.1.1 FineBI简介 FineBI 是帆软软件有限公司推出的一款商业智能&#xff08;Business Intelligence&#xff09;产品。 FineBI 是新一代大数据分析的 BI 工具&#xff0c;旨在帮助企业的业务人员充分了解和利用他们的数据。FineBI 凭…

一篇文章讲解清楚ARM9芯片启动流程

SAM9X60 ARM9 boot启动流程关键词介绍&#xff1a; 第一级bootloader - 也叫boot ROM&#xff0c;是集成在MPU内部的ROM里面 它的主要功能是执行对MPU的基本初始化和配置&#xff0c;查找并将第二级bootloader从外部NVM中读取出来并放到MPU内部的SRAM. 可以让MPU强制停留在第一…

【JavaSE-6】数组的定义与使用

1、数组的基本概念 1.1、为什么使用数组 为了方便将同一种数据类型的数据进行存储。 1.2、什么是数组 指的是一种容器&#xff0c;可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。如&#xff1a;定义一个int类型的数组…

基于eRDMA实测DeepSeek开源的3FS

DeepSeek昨天开源了3FS分布式文件系统, 通过180个存储节点提供了 6.6TiB/s的存储性能, 全面支持大模型的训练和推理的KVCache转存以及向量数据库等能力, 每个客户端节点支持40GB/s峰值吞吐用于KVCache查找. 发布后, 我们在阿里云ECS上进行了快速的复现, 并进行了性能测试, ECS…

Linux网络编程(20250301)

网络通信&#xff1a;进行不同主机的进程间通信 解决硬件与软件的互联互通 主机-->交换机-->路由器-->广域网-->路由器-->交换机-->主机 IP地址&#xff1a;区分不同主机 MAC地址&#xff1a;计算机硬件地址 端口号&#xff1a;区分主机上的不同进程 1…

JAVA安全—手搓内存马

前言 最近在学这个内存马&#xff0c;就做一个记录&#xff0c;说实话这个内存马还是有点难度的。 什么是内存马 首先什么是内存马呢&#xff0c;顾名思义就是把木马打进内存中。传统的webshell一旦把文件删除就断开连接了&#xff0c;而Java内存马则不同&#xff0c;它将恶…

HarmonyOS学习第11天:布局秘籍RelativeLayout进阶之路

布局基础&#xff1a;RelativeLayout 初印象 在 HarmonyOS 的界面开发中&#xff0c;布局是构建用户界面的关键环节&#xff0c;它决定了各个组件在屏幕上的位置和排列方式。而 RelativeLayout&#xff08;相对布局&#xff09;则是其中一种功能强大且灵活的布局方式&#xff0…

【Bootstrap5】Bootstrap5学习笔记

目的 学完Blazor以后&#xff0c;我自己用这个写了一个小工具&#xff0c;但是我发现自己对前端粗浅的认知确实很难把UI层的组件弄出我想要的样子&#xff0c;所以我思来想去决定再把前端知识补一补.记录基于菜鸟教程的Bootstrap5教程&#xff0c;然后有些不清楚的我还补充一些…

【JMeter】JMeter之MQTT压测

文章目录 MQTT概念Jmeter压测MQTTMQTT服务器下载Jmeter MQTT插件测试MQTT测试思路和解决方法 MQTT概念 MQTT是什么 MQTT是用于物联网&#xff08;IoT&#xff09;的OASIS标准消息传递协议。它被设计为一种非常轻量级的发布/订阅消息传输&#xff0c;非常适合使用较少的代码占用…

Android U 分屏——SystemUI侧处理

WMShell相关的dump命令 手机分屏启动应用后运行命令&#xff1a;adb shell dumpsys activity service SystemUIService WMShell 我们可以找到其中分屏的部分&#xff0c;如下图所示&#xff1a; 分屏的组成 简图 分屏是由上分屏(SideStage)、下分屏(MainStage)以及分割线组…

一键安装Nginx部署脚本之Linux在线安装Nginx,脚本化自动化执行服务器部署(附执行脚本下载)

相关链接 一键安装Nginx部署脚本之Linux在线安装Nginx一键安装Redis部署脚本之Linux在线安装Redis一键安装Mysql部署脚本之Linux在线安装Mysql一键安装JAVA部署脚本之Linux在线安装JDKXshell客户端免费版无需注册XFtp客户端免费版无需注册 前言 简化服务器部署操作&#xff0…

yum源选要配置华为云的源,阿里云用不了的情况

curl -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo

软考中级-数据库-3.2 数据结构-数组和矩阵

数组 一维数组是长度固定的线性表&#xff0c;数组中的每个数据元素类型相同。n维数组是定长线性表在维数上的扩张&#xff0c;即线性表中的元素又是一个线性表。 例如一维数组a[5][a1,a2,a3,a4,a5] 二维数组a[2][3]是一个2行2列的数组 第一行[a11,a12,a13] 第二行[a21,a22,a23…

微服务组件详解——sentinel

1.启动sentinel&#xff1a; 下载jar sentinel-dashboard-1.8.0.jar 使用以下命令直接运行 jar 包&#xff08;JDK 版本必须≥ 1.8&#xff09;&#xff1a; java -Dserver.port9999 -jar D:\sentinel-dashboard-1.8.0.jar 控制台访问地址&#xff1a;http://localhost:9999…