基于vue2+ElementUI的el-tree封装一个带搜索的树形组件

news/2025/4/22 2:22:55

需求

在这里插入图片描述
实现一个如图带搜索框的下拉树形组件。

解决方案

利用el-input+el-tree实现自定义带搜索的下拉树形组件。

具体实现步骤

1、创建TreeSelect组件

<template><div class="tree-select-wrapper" v-clickoutside="handleClose"><el-inputclass="common-simple-input tree-select-input"v-model="selectedText":placeholder="placeholder":clearable="clearable":disabled="disabled":style="styleAttr"readonly@click.native="handleClick"@clear="handleClear"><iclass="el-input__icon":class="['el-icon-arrow-down', visible ? 'is-reverse' : '']"slot="suffix"></i></el-input><div v-show="visible" class="tree-select-dropdown" :style="styleAttr"><el-inputv-if="filterable"v-model="filterText"class="tree-select-filter common-simple-input"placeholder="请输入关键字进行过滤"clearable@click.native.stop></el-input><el-treeref="tree":data="options":props="defaultProps":node-key="nodeKey":default-expand-all="defaultExpandAll":expand-on-click-node="expandOnClickNode":filter-node-method="handleFilterNode"@node-click="handleNodeClick"></el-tree></div></div>
</template><script>
export default {name: 'TreeSelect',props: {value: {type: [String, Number],default: ''},textValue: {type: String,default: ''},placeholder: {type: String,default: '请选择'},options: {type: Array,default: () => []},defaultProps: {type: Object,default: () => ({children: 'children',label: 'label',value: 'value'})},nodeKey: {type: String,default: 'value'},defaultExpandAll: {type: Boolean,default: false},expandOnClickNode: {type: Boolean,default: true},filterable: {type: Boolean,default: true},clearable: {type: Boolean,default: true},disabled: {type: Boolean,default: false},styleAttr: {type: Object,default: () => ({})}},data() {return {visible: false,filterText: '',selectedText: this.textValue}},watch: {filterText(val) {this.$refs.tree.filter(val)},textValue(val) {this.selectedText = val},visible: {immediate: true,deep: true,handler(val) {if (val && this.$refs.tree) {this.$refs.tree.setCurrentKey(this.value)}}}},mounted() {if (this.value && this.$refs.tree) {this.$refs.tree.setCurrentKey(this.value)}},methods: {handleClick() {if (this.disabled) returnthis.visible = !this.visible},handleClose() {this.visible = false},handleClear() {this.$emit('input', '')this.$emit('update:textValue', '')this.$emit('change', '')this.selectedText = ''},handleNodeClick(node) {if (!node[this.nodeKey]) returnthis.$emit('input', node[this.nodeKey])this.$emit('update:textValue', node[this.defaultProps.label])this.$emit('change', node[this.nodeKey])this.selectedText = node[this.defaultProps.label]this.visible = false},handleFilterNode(value, data) {if (!value) return trueconst label = data[this.defaultProps.label] || ''return label.indexOf(value) !== -1}},directives: {clickoutside: {bind(el, binding) {function documentHandler(e) {if (el.contains(e.target)) {return false}if (binding.value) {binding.value()}}el.__vueClickOutside__ = documentHandlerdocument.addEventListener('click', documentHandler)},unbind(el) {document.removeEventListener('click', el.__vueClickOutside__)delete el.__vueClickOutside__}}}
}
</script><style lang="scss" scoped>
.tree-select-wrapper {position: relative;width: 100%;.tree-select-input {cursor: pointer;:deep(.el-input__suffix) {margin-right: vw(5);margin-top: vh(2);font-size: vw(14);}:deep(.el-input__icon) {transition: transform 0.3s;&.is-reverse {transform: rotateZ(180deg);}}}.tree-select-dropdown {width: 100%;position: absolute;top: 100%;left: 0;z-index: 1000;margin-top: 5px;padding: 5px 0;background-color: #152e58;border: 1px solid #0d59b4;border-radius: 4px;box-shadow: 0 2px 12px 0 rgba(112, 177, 218, 0.5);max-height: 400px;overflow-y: auto;cursor: pointer;.tree-select-filter {margin: 0 5px 5px;width: 90%;}:deep(.el-tree) {border: none;background: none !important;.el-tree__empty-text {color: #fff;font-size: vw(14);}.el-tree-node__label {cursor: pointer;color: #fff;font-size: vw(14) !important;}.el-tree-node__content {background: none !important;&:hover {color: #6cd9ff;background-color: rgba(27, 40, 61, 0.3) !important;}}.el-icon-caret-right:before {content: "\E791" !important;}.el-tree-node__expand-icon.expanded {transform: rotate(90deg) !important;-webkit-transform: rotate(90deg) !important;}.el-tree-node.is-current.is-focusable {background-color: rgba(27, 40, 61, 0.5) !important;.el-tree-node__label {color: #6cd9ff !important;}}}}
}
</style> 

2、使用TreeSelect组件

// 引入TreeSelect组件
import TreeSelect from "@/components/TreeSelect/index.vue";// 使用示例<TreeSelectv-model="searchForm.orgCode":text-value.sync="searchForm.orgName":options="orgTreeData"placeholder="请选择":default-props="{children: 'children',label: 'orgName',value: 'orgCode',}"node-key="orgCode":filterable="true":clearable="true":styleAttr="{ width: '200px' }"/>data() {orgTreeData: [],
},
mounted() {// 获取树形数据this.getOrgTreeData();},
methods: {// 获取树形数据方法async getOrgTreeData() {try {const res = await this.getOrgTreeListApi();this.orgTreeData = res.data || [];} catch (error) {console.error("获取事业部树形数据失败:", error);}},getOrgTreeListApi async(data) {return axios.post(`/api/org/tree`, data).then((resp) => resp.data)}
}              

写在最后

TreeSelect组件可以直接Copy进行使用,其中common-simple-input为图中el-input输入框的蓝底亮框样式,可根据自身需求进行样式自定义开发。


https://dhexx.cn/news/show-5497388.html

相关文章

Margin和Padding在WPF和CSS中的不同

CSS和WPF中 margin 与 padding 在方向上的规定基本一致&#xff0c;但在使用场景和一些细节上有所不同。 CSS - 方向规定&#xff1a; margin 和 padding 属性可以分别指定上、右、下、左四个方向的值。例如 margin:10px 20px 30px 40px; 表示上外边距为10px、右外边距为20…

实现添加用户和SpringBoot-实现修改和删除

实现跳转到修改页面&#xff1a; GetMapping("/updateuser.html") public String updateUser(Integer id,Model model){User user userService.getOneById(id);model.addAttribute("user",user);List<Address> addresses addressService.getAll()…

bash的特性-常用的通配符

在Linux或Unix系统中&#xff0c;Bash作为最常用的命令行解释器之一&#xff0c;提供了多种通配符&#xff08;wildcards&#xff09;来帮助用户更高效地进行文件操作。这些通配符可以用来匹配多个文件名或路径名&#xff0c;极大地简化了批量处理任务。本文将详细介绍Bash中常…

Ubuntu安装yum遇到Package ‘yum‘ has no installation candidate

环境说明 Window11&#xff0c;WSL2&#xff0c;Ubuntu24.04 错误描述 rootLAPTOP:~# apt-get install yum Reading package lists... Done Building dependency tree... Done Reading state information... Done Package yum is not available, but is referred to by anot…

【AI提示词】运营经理

提示说明 运营经理是企业中负责日常运营管理的关键角色&#xff0c;通过专业的运营管理知识&#xff0c;帮助企业实现目标和提升效益。 提示词 # 角色 运营经理## 注意 运营经理旨在为用户提供高效的运营管理建议和策略&#xff0c;帮助用户在实际工作中提升效率和效果。## …

【Sequelize】关联模型和孤儿记录

一、关联模型的核心机制 1. 关联类型与组合规则 • 基础四类型&#xff1a; • hasOne&#xff1a;外键存储于目标模型&#xff08;如用户档案表存储用户ID&#xff09; • belongsTo&#xff1a;外键存储于源模型&#xff08;如订单表存储用户ID&#xff09; • hasMany&…

GPTNet如何革新创意与效率

引言 人工智能正在以前所未有的速度改变我们的工作与生活方式&#xff0c;从智能写作到视觉创作&#xff0c;AI工具已成为不可或缺的伙伴。在众多平台中&#xff0c;GPTNet以其强大的功能整合和直观体验崭露头角。它不仅汇集了GPT系列、Claude、Grok、Gemini等顶级对话模型&am…

Debian服务器挂载外部存储设备的完整指南

在 Debian 系统中挂载外部存储设备(如 U 盘、移动硬盘、SSD)是服务器运维和桌面使用中非常常见的操作。本文将为你详细拆解从识别设备、格式化到手动/自动挂载的全过程&#xff0c;适合新手到进阶用户参考。 一、准备阶段&#xff1a;插入存储设备并识别 1. 插入外部设备后查看…

ns-3中UDP饱和流发包时间间隔设置最合理值

ns3的官方手册很全&#xff0c;相关书籍也是有的&#xff0c;官网先贴在这里&#xff1a; ns-3 | a discrete-event network simulator for internet systemsa discrete-event network simulator for internet systemshttps://www.nsnam.org/相关的脚本介绍也都有一些&#xf…

V型调节阀:专为解决锂电池行业碳酸锂结晶介质的革命性方案-耀圣

V型调节阀&#xff1a;专为解决锂电池行业碳酸锂结晶介质的革命性方案 随着全球新能源汽车及储能产业的爆发式增长&#xff0c;锂电池核心材料碳酸锂的需求持续攀升。然而&#xff0c;碳酸锂生产过程中的结晶环节常面临介质堵塞、粒度不均、效率低下等难题&#xff0c;直接影…