当前位置: 首页 > news >正文

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-treev-loading="loading":data="treeData"ref="tree":props="defaultProps"node-key="id"accordiondefault-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事件也可以获取选中的节点

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

http://www.lryc.cn/news/547096.html

相关文章:

  • 《底层逻辑》总结书摘
  • 【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)
  • 【微信小程序】每日心情笔记
  • PMP项目管理—沟通管理篇—3.监督沟通
  • 在Linux中开发OpenGL——检查开发环境对OpenGL ES的支持
  • 低空经济-飞行数据平台 搭建可行方案
  • python量化交易——金融数据管理最佳实践——使用qteasy大批量自动拉取金融数据
  • 为AI聊天工具添加一个知识系统 之136 详细设计之77 通用编程语言 之7
  • 【CSRF实践】DVWA靶场之CSRF实践
  • 数据库设计方面如何进行PostgreSQL 17的性能调优?
  • [场景题]如何实现购物车
  • Rust 并发编程:Futures、Tasks 和 Threads 的结合使用
  • 常见的网络协议介绍
  • 一文读懂加载地址、链接地址和运行地址
  • Unity帧同步与状态同步混合架构开发指南
  • 后路式编程
  • Rust语言入门与应用:未来发展趋势解析
  • 【2025小白版】计算复试/保研机试模板(个人总结非GPT生成)附代码
  • android11使用gpio口控制led状态灯
  • 基于Asp.net的高校一卡通管理系统
  • C++蓝桥杯基础篇(七)
  • 8.路由原理专题
  • jQuery UI 简介
  • Web服务器配置
  • LINUX网络基础 [一] - 初识网络,理解网络协议
  • 定制化开发的WooCommerce独立站商城更安全
  • Xcode 运行真机失败
  • 【FFmpeg之如何新增一个硬件解码器】
  • P3385 【模板】负环
  • 破解透明物体抓取难题,地瓜机器人CASIA 推出几何和语义融合的单目抓取方案|ICRA 2025