基于vue2.6+ElementUI实现的可搜索下拉选择树
效果图
使用实示例
<el-form-item label="上级单位" prop="parentId">
<el-select-tree v-if="parentOpt.length>0" :list="parentOpt" v-model="form.parentId" @change="parentChange" placeholder="请选择上级单位" />
</el-form-item>
parentChange(data: any) {
//data为当前选中对象
console.log(data)
}
组件代码
html
<template>
<div class="selectTree">
<el-select ref="elSelect" v-model="newVal" :placeholder="placeholder" filterable :filter-method="filterTree" clearable @clear="clear" popper-append-to-body>
<el-option :value="newVal" :label="label" class="hasTree" disabled>
<el-tree
:data="openSearch ? searchData : list"
ref="tree"
node-key="value"
:expand-on-click-node="false"
:default-expanded-keys="defaultExpandedKeys"
:current-node-key="newVal"
highlight-current
check-on-click-node
auto-expand-parent
@node-click="handleNodeClick"
></el-tree>
</el-option>
</el-select>
</div>
</template>
js
<script>
export default {
name: 'ElSelectTree',
props: {
value: {
type: String,
require: true,
},
list: {
//树状列表:{label:'',value:'',children:[]}
type: Array,
default: () => {
return [];
},
},
placeholder: {
type: String,
default: '请选择',
},
},
data() {
return {
newVal: '', //本页面选中的数据
label: '',
selectTree: {},
defaultExpandedKeys: [], //默认展开
searchData: [], //带搜索数据
openSearch: false, //是否开启搜索
};
},
watch: {
value: {
handler(value) {
this.newVal = value;
if (value) {
this.defaultExpandedKeys = [value];
this.$refs.tree.setCurrentKey(value); //设置默认选择
const check = this.findLabel(this.list, value);
if (check) {
this.label = check.label;
}
}
},
deep: true, // 深度监听
immediate: true, //首次触发
},
newVal(value) {
const check = this.findLabel(this.list, value);
if (check) {
this.label = check.label;
}
this.$emit('input', value);
},
},
created() {
// el-select 中加了filterable 点击箭头回收不去问题
Object.getPrototypeOf(this.$options.components).ElSelect.options.methods.handleFocus = () => {};
},
mounted() {},
methods: {
//节点选择事件
handleNodeClick(data) {
this.newVal = data.value;
this.label = data.label;
this.$refs.elSelect.blur();
this.searchData = [];
this.openSearch = false;
this.$emit('change', data);
},
//筛选树
async filterTree(value) {
if (value) {
this.openSearch = true;
this.searchData = [];
await this.findItem(this.list, value);
} else {
this.openSearch = false;
this.searchData = [];
}
},
//递归筛选,查询时用
findItem(arr, value) {
return new Promise(resolve => {
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item.label.includes(value)) {
this.searchData.push(item);
} else if (item.children && item.children.length > 0) {
this.findItem(item.children, value);
}
}
resolve(true);
});
},
//递归筛选,回显label
findLabel(arr, value) {
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item.value === value) {
return item;
} else if (item.children && item.children.length > 0) {
const result = this.findLabel(item.children, value);
if (result) {
return result;
}
}
}
},
//清空事件
clear() {
this.$refs.tree.setCurrentKey(null); //清空高亮
this.label = '';
this.newVal = '';
this.searchData = [];
this.openSearch = false;
this.$emit('change', {});
},
},
};
</script>
css
<style scoped lang="scss">
.selectTree {
display: inline-block;
width: 100%;
}
.el-select {
width: 100%;
}
.hasTree {
padding: 0 !important;
margin: 0;
overflow: auto;
line-height: normal;
height: auto;
cursor: default !important;
font-weight: 500 !important;
::v-deep .el-tree-node__content {
height: 34px;
line-height: 34px;
}
::v-deep .el-tree-node__label {
font-size: 14px !important;
}
}
</style>
附带平级转树级方法
http://t.csdnimg.cn/I2x3t