vue2结合element-ui实现TreeSelect 树选择功能

本文主要是介绍vue2结合element-ui实现TreeSelect 树选择功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

需求背景

在日常开发中,我们会遇见很多不同的业务需求。如果让你用element-ui实现一个 tree-select 组件,你会怎么做?

这个组件在 element-plus 中是有这个组件存在的,但是在 element-ui 中是没有的。

可能你会直接使用 element-plus 组件库,或者其他组件库。但是若你的项目目前的基于vue3和element-ui进行开发的呢?

最终效果

大致思路:

el-select和el-tree进行嵌套,将el-tree放到el-option里,循环遍历el-option,同时定义一个方法比如:formatData,对树形数据进行递归处理,这样就可以实现无论嵌套的层级有几层都可以正常渲染在界面上
利用 v-model 和 update:selectValue 实现父子组件之间的双向通信,同时利用computed进行监听以实现实时更新

组件中的 v-model

我们在input中可以使用v-model来完成双向绑定:

  •  这个时候往往会非常方便,因为v-model默认会帮助我们完成两件事:
  •  v-bind:value的数据绑定和@input的事件监听;

如果我们现在封装了一个组件,其他地方在使用这个组件时,是否也可以使用v-model来同时完成这两个功能呢?

当我们在组件上使用的时候,等价于如下的操作:

  •  我们会发现和input元素不同的只是属性的名称和事件触发的名称而已;

如果我们希望绑定多个属性呢?

  •  也就是我们希望在一个组件上使用多个v-model是否可以实现呢?
  •  我们知道,默认情况下的v-model其实是绑定了 modelValue 属性和 @update:modelValue的事件;
  •  如果我们希望绑定更多,可以给v-model传入一个参数,那么这个参数的名称就是我们绑定属性的名称;

实现代码示例

子组件:

<template><div><h4>Counter: {{modelValue}}</h4><button @click="changeCounter">修改数据</button></div>
</template><script>
export default {props: {modelValue:  {type: Number},},emits: ['update:modelValue'],methods: {changeCounter(){this.$emit('update:modelValue',101)}}
}
</script>

父组件:

<template><!-- <child v-model="appCounter" /> --><!-- 等同于如下做法:modelValue--默认可以自定义名称,通过 v-model:counter 类似于这种格式--><child :modelValue="appCounter" @update:modelValue="appCounter = $event" />
</template><script>
import child from '@/components/child.vue'
export default {components: {child},data() {return {appCounter: 100,};},methods: {},
};
</script>

有了上面的知识,那么下面实现就很简单了,这里直接上代码 

组件封装

子组件:TreeSelect.vue

<template><div class="app-container" style="padding: 0"><el-selectclass="main-select-tree"ref="selectTree"v-model="value"style="width: 240px"clearable@clear="clearSelectInput"><el-inputstyle="width: 220px; margin-left: 10px; margin-bottom: 10px"placeholder="输入关键字进行过滤"v-model="filterText"clearable></el-input><el-optionv-for="item in formatData(data)":key="item.value":label="item.label":value="item.value"style="display: none"/><el-treeclass="main-select-el-tree"ref="selecteltree":data="data"node-key="id"highlight-current:props="defaultProps"@node-click="handleNodeClick":current-node-key="value":expand-on-click-node="true"default-expand-all:filter-node-method="filterNode"/></el-select></div>
</template><script>
export default {props: {selectValue: {type: String,default: "",},},data() {return {filterText: "",value: "",data: [{id: 1,label: "云南",children: [{id: 2,label: "昆明",children: [{id: 3,label: "五华区",children: [{id: 8,label: "xx街道",children: [{id: 81,label: "yy社区",children: [{ id: 82, label: "北辰小区" }],},],},],},{ id: 4, label: "盘龙区" },],},],},{id: 5,label: "湖南",children: [{ id: 6, label: "长沙" },{ id: 7, label: "永州" },],},{id: 12,label: "重庆",children: [{ id: 10, label: "渝北" },{ id: 9, label: "合川" },],},{id: 13,label: "江苏",children: [{ id: 14, label: "盐城" }],},],defaultProps: {children: "children",label: "label",},};},watch: {filterText(val) {this.$refs.selecteltree.filter(val);},},methods: {filterNode(value, data) {if (!value) return true;return data.label.indexOf(value) !== -1;},// 递归遍历数据formatData(data) {let options = [];const formatDataRecursive = (data) => {data.forEach((item) => {options.push({ label: item.label, value: item.id });if (item.children && item.children.length > 0) {formatDataRecursive(item.children);}});};formatDataRecursive(data);return options;},// 点击事件handleNodeClick(node) {this.value = node.id;this.$refs.selectTree.blur();this.$emit('update:selectValue', node.label);},// 清空事件clearSelectInput() {this.$emit('update:selectValue', '');// 获取 el-tree 实例的引用const elTree = this.$refs.selecteltree;// 将当前选中的节点设置为 nullelTree.setCurrentKey(null);},},
};
</script><style>
.main-select-el-tree .el-tree-node .is-current > .el-tree-node__content {font-weight: bold;color: #409eff;
}
.main-select-el-tree .el-tree-node.is-current > .el-tree-node__content {font-weight: bold;color: #409eff;
}
</style>
使用方式
<TreeSelect v-model="selectedValue" @update:selectValue="handleSelectValueChange"></TreeSelect><el-button size="medium" :disabled="todoIsTotal">交接当前{{ tableData.length }}条任务</el-button>import TreeSelect from "./TreeSelect.vue";export default {components: {TreeSelect,},data() {selectedValue: "",},computed: {todoIsTotal() {return this.selectedValue === "";},},methods: {handleSelectValueChange(value) {if (value && value.length > 0) {this.selectedValue = value;} else {this.selectedValue = "";}},},
}

这篇关于vue2结合element-ui实现TreeSelect 树选择功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/968178

相关文章

Java设计模式之代理模式2-动态代理(jdk实现)

这篇是接着上一篇继续介绍java设计模式之代理模式。下面讲解的是jdk实现动态代理。 1.)首先我们要声明一个动态代理类,实现InvocationHandler接口 package com.zhong.pattern.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/*** 演

使用Array实现Java堆栈

本教程给出了使用Array 实现Stack数据结构的示例。堆栈提供将新对象放在堆栈上(方法push())并从堆栈中获取对象(方法pop())。堆栈根据后进先出(LIFO)返回对象。请注意,JDK提供了一个默认的Java堆栈实现作为类java.util.Stack。 适用于所有堆栈实现的两个强制操作是: push():数据项放置在堆栈指针指向的位置。pop():从堆栈指针指向的位置删除并返回数据

Apache Shiro会话管理功能-07

Apache Shiro会话管理功能 会话是您的用户在使用您的应用程序时携带一段时间的数据桶。传统上,会话专用于Web或EJB环境。Shiro支持任何应用程序环境的会话。此外,Shiro还提供许多其他强大功能来帮助您管理会话。 特征 基于POJO / J2SE(IoC) - Shiro中的所有内容(包括会话和会话管理的所有方面)都是基于接口的,并使用POJO实现。这允许您使用任何与Ja

Apache Shiro授权功能-05

Apache Shiro授权功能 授权(也称为访问控制)是确定应用程序中资源的访问权限的过程。换句话说,确定“谁有权访问什么。”授权用于回答安全问题,例如“用户是否允许编辑帐户”,“该用户是否允许查看此网页”,“该用户是否可以访问”到这个按钮?“这些都是决定用户有权访问的决定,因此都代表授权检查。 授权是任何应用程序的关键元素,但它很快就会变得非常复杂。Shiro的目标是消除授权的大部分复杂性

Apache Shiro身份验证功能-04

Apache Shiro身份验证功能 身份验证是身份验证的过程 - 您试图验证用户是否是他们所说的人。为此,用户需要提供系统理解和信任的某种身份证明。 Shiro框架旨在使身份验证尽可能干净和直观,同时提供丰富的功能。以下是Shiro身份验证功能的一个亮点。 特征 基于主题 - 您在Shiro中执行的几乎所有操作都基于当前正在执行的用户,称为主题。您可以轻松地在代码中的任何位置检索主题。

Redis利用zset数据结构如何实现多字段排序,score的调整(finalScore = score*MAX_NAME_VALUE + getIntRepresentation(name) )

1、原文:   2、使用sql很容易实现多字段的排序功能,比如: select * from user order by score desc,name desc; 3、问题:用两个字段(score,name)排序。在redis中应该怎么做?   4、使用按分数排序的redis集合。你必须根据你的需要准备分数。 finalScore = score*MAX_NAME_VALUE +

字符串处理函数strchr和strstr的实现

1,strchr函数 函数功能:查找一个字符。在一个字符串中查找一个特定的字符。 函数原型:char *strchr(char const *str,int ch); 函数说明:strchr在字符串str中查找字符ch第一次出现的位置,找到后返回一个指向该位置的指针。如果该字符不存在于字符串中,则返回一个NULL指针。注意:第二个参数是一个整型值,但是,它包含了一个字符串值。

关于HTML的多媒体标签

代码示例如下: <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="Generator" content="EditPlus?"><meta name="Author" content=""><meta name="Keywords" content=""><meta name="Descriptio

关于HTML的框架标签及内嵌框架

框架标签的代码示例如下: <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="Generator" content="EditPlus?"><meta name="Author" content=""><meta name="Keywords" content=""><meta name="Desc

关于HTML的表格标签

代码示例如下: <!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="Generator" content="EditPlus?"><meta name="Author" content=""><meta name="Keywords" content=""><meta name="Descriptio