目录要树
```components
components
├─ TreeSelect2
│ └─ index.vue
```
---
TreeSelect2/index.vue
<template>
<div class="tree-select-item">
<el-select v-model="selectNodeLabel" v-popover:tree-select-popover class="selectbox" :placeholder="placeholder" :disabled="disabled"
:clearable="clearable" popper-class="select-option" :popper-append-to-body="false" @clear="handleClear" />
<el-popover :width="selectW" ref="tree-select-popover" v-model="visible" :disabled="disabled" placement="bottom-start"
popper-class="tree-select-popper" :visible-arrow="false" trigger="click">
<el-input v-if="showFilterInput" v-model="filterText" class="tree-select-filter-input" placeholder="输入关键字进行过滤" clearable />
<el-scrollbar ref="scroll">
<el-tree ref="tree" v-loading='treeLoading' :data="data" :props="props" :node-key="nodeKey" :filter-node-method="filterNode"
highlight-current :default-checked-keys="checkedKeys" :expand-on-click-node="false" accordion style="height: 250px"
@current-change="handleChange">
<span slot-scope="{ node, data }" class="custom-tree-node">
<span>
<i :class="data.icon" />
{
{ node.label }}
</span>
</span>
</el-tree>
</el-scrollbar>
</el-popover>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: "TreeSelect2",
props: {
data: {
type: Array,
default: null
},
nodeKey: {
type: String,
default: "deptId"
},
props: {
type: Object,
default() {
return { label: "name", children: "children" }
}
},
showFilterInput: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
selectKey: {
default: null
},
selectLabel: {
type: String,
default: null
},
placeholder: {
type: String,
default: "请选择"
},
clearable: {
type: Boolean,
default: false
}
},
data() {
return {
selectW: "",
valueId: null,
filterText: "",
checkedKeys: [1],
visible: false,
selectNodeKey: null,
selectNodeLabel: null,
currentNode: null,
currentData: null
}
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
},
selectKey() {
this.selectNodeKey = this.selectKey
},
selectLabel: {
handler(val) {
this.selectNodeLabel = val
},
immediate: true
},
selectNode() {
this.currentNode = this.selectNode
},
selectData() {
this.currentData = this.selectData
}
},
created() { },
mounted() {
this.selectW =
document.getElementsByClassName("selectbox")[0].offsetWidth - 30
},
computed: {
...mapGetters(['treeLoading'])
},
methods: {
filterNode(value, data) {
if (!value) {
return true
}
return data.label.indexOf(value) !== -1
},
handleChange(data, node) {
this.visible = false
this.selectNodeKey = data.id
this.selectNodeLabel = node.label
this.currentNode = node
this.currentData = node.data
this.updateParentData(data, node)
},
handleClear() {
this.visible = false
this.selectNodeKey = null
this.selectNodeLabel = null
this.currentNode = null
this.currentData = null
this.filterText = null
this.updateParentData(null, null)
},
reset() {
this.selectNodeLabel = ""
},
updateParentData(data, node) {
this.$emit("update:selectKey", this.selectNodeKey)
this.$emit("update:selectLabel", this.selectNodeLabel)
this.$emit("update:selectNode", this.currentNode)
this.$emit("update:selectData", this.currentData)
this.$emit("change", data, node)
},
setValue(key, label) {
this.selectNodeKey = key
this.selectNodeLabel = label
},
getNode(key) {
if (key) {
this.$refs.tree.setCurrentKey(key)
const node = this.$refs.tree.getNode(key)
this.selectNodeLabel = node.label
this.currentNode = node
this.currentData = node.data
}
}
}
}
</script>
<style lang="scss" scoped>
.el-scrollbar {
/deep/ .is-horizontal {
height: 0 !important;
left: 0 !important;
}
/deep/.el-scrollbar__wrap {
overflow-x: hidden;
}
::-webkit-scrollbar-track-piece {
background-color: #fff !important;
}
::-webkit-scrollbar {
width: 5px;
height: 9px;
}
.custom-tree-node {
font-size: 18px;
}
::-webkit-scrollbar-thumb {
background-color: #bfc3cc;
cursor: pointer !important;
background-clip: padding-box;
min-height: 28px;
}
.custom-tree-node {
font-size: 16px;
}
}
/deep/ .el-tree {
min-width: 280px;
max-width: 500px;
overflow: auto;
}
/deep/ .el-tree > .el-tree-node {
display: inline-block;
min-width: 100%;
}
.tree-select-item {
.select-option {
display: none !important;
}
}
.tree-select-filter-input {
margin-bottom: 6px;
}
</style>
页面使用
<tree-select-2 class="width240" ref="treeSelect" :data="sysDeptList" :props="{
label: 'label',
children: 'children'
}" :select-key.sync="deptId" :select-label.sync="deptName" />