<template>
<div class="select_tree_box">
<el-select
v-model="dataValue"
clearable
filterable
ref="treeSelect"
:multiple="multiple"
collapse-tags
collapse-tags-tooltip
:placeholder="placeholder || '请选择'"
:filter-method="selectFilter"
@clear="clearSelected"
@change="selectChange"
>
<el-option v-for="op in selsectOptions" :key="op.value" :value="op.value" :label="op.label">
<span>{{ op.label }}</span>
</el-option>
<el-option :value="select.currentNodeKey" :label="select.currentNodeLabel" v-show="selsectOptions.length == 0">
<el-tree-v2
id="tree_v2"
style="width: 300px"
ref="treeV2"
:data="listData"
:height="240"
:indent="6"
@node-click="nodeClick"
:expand-on-click-node="false"
:filter-method="treeFilter"
>
<template #default="{ node }">
<div class="i-custom-tree" :class="{ active: multiple ? dataValue?.includes(node.data.value) : dataValue == node.data.value }">
<div style="width: 120px">{{ node.label }}</div>
<el-icon v-if="multiple ? dataValue?.includes(node.data.value) : dataValue == node.data.value"><Select /></el-icon>
</div>
</template>
</el-tree-v2>
</el-option>
<el-option v-for="op in options" :key="op.value" :value="op.value" :label="op.label"> <span></span> </el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { TreeNodeData } from 'element-plus/es/components/tree/src/tree.type';
//树数据请求接口
import { userDeptTree } from '/@/api/system/dept';
const props = defineProps({
//是否多选
multiple: {
type: Boolean,
default: false,
},
//提示信息
placeholder: {
type: String,
default: '请选择',
},
showRoot: {
type: Boolean,
default: false,
},
//是否排除供应商
isExcludeSupplier: {
type: Boolean,
default: false,
},
});
const model = defineModel();
const dataValue = ref();
const listData = ref([]);
const options = ref([]);
const selsectOptions = ref([]);
const select: any = reactive({
currentNodeKey: '',
currentNodeLabel: '',
});
const treeSelect = ref<HTMLElement | null>(null);
watch(
() => model.value,
(newValue: any, oldValue: any) => {
console.log('props.multiple', props.multiple);
if (props.multiple) {
// 多选模式
// data.value=[]
dataValue.value = newValue || [];
console.log(model.value, 'model.value');
} else {
// 单选模式
dataValue.value = '';
dataValue.value = newValue;
}
},
{ immediate: true }
);
onMounted(() => {
console.log(model.value, 'model.value');
if (props.multiple) {
// 多选模式
dataValue.value = model.value || [];
console.log(model.value, 'model.value');
} else {
// 单选模式
dataValue.value = model.value || '';
}
// 服务端请求数据
userDeptTree(props.isExcludeSupplier).then((res: any) => {
if (res.code == 0) {
if (props.showRoot) {
const obj = {
value: '0',
label: '根组织',
disabled: true,
children: [] as any[],
};
obj.children = res.data;
listData.value = [obj];
} else {
listData.value = res.data;
}
}
});
});
const clearSelected = () => {
model.value = '';
};
const treeV2: any = ref<HTMLElement | null>(null);
const selectFilter = (query: string) => {
selsectOptions.value = [];
treeV2.value.filter(query);
};
const nodeClick = (data: any, node: any) => {
select.currentNodeKey = data.value;
select.currentNodeLabel = data.label;
nextTick(() => {
options.value.push({
value: data.value,
label: data.label,
});
});
if (props.multiple) {
dataValue.value.push(data.value);
model.value = dataValue.value;
} else {
// 单选模式
model.value = data.value;
}
(treeSelect.value as any).blur();
};
const selectChange = (value: any) => {
for (let index = 0; index < value.length; index++) {
const op = selsectOptions.value?.find((item: any) => item.value == value[index]);
if (op) {
const n = options.value.findIndex((item: any) => item.value == op.value);
if (n >= 0) {
options.value.push(op);
}
}
}
(treeSelect.value as any).blur();
};
const treeFilter = (query: string, node: TreeNodeData) => {
if (query && node.label!.includes(query)) {
nextTick(() => {
selsectOptions.value.unshift({
label: node.label,
value: node.value,
});
});
}
return query ? false : true;
};
const handleChange = (value: any) => {
if (props.multiple) {
// 多选模式
model.value = value;
} else {
// 单选模式
model.value = value;
}
};
</script>
<style lang="scss" scoped>
.select_tree_box {
width: 100%;
}
:deep(.el-select__selection) {
width: 214px;
}
:deep(.el-tag.is-closable) {
max-width: 130px !important;
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.is-selected:after {
content: none;
}
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
height: auto;
max-height: 274px;
padding: 0;
overflow: hidden;
}
.el-select-dropdown__item.selected {
font-weight: normal;
}
ul li :deep(.el-tree .el-tree-node__content) {
height: auto;
padding: 0 20px;
}
.el-tree-node__label {
font-weight: normal;
}
.el-tree :deep(.is-current .el-tree-node__label) {
color: #409eff;
font-weight: 700;
}
.el-tree :deep(.is-current .el-tree-node__children .el-tree-node__label) {
color: #606266;
font-weight: normal;
}
.selectInput {
padding: 0 5px;
box-sizing: border-box;
}
.el-select {
width: 100% !important;
}
.i-custom-tree {
font-weight: 100;
}
.i-custom-tree.active {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
font-weight: 100;
color: var(--next-main-color);
.el-icon {
padding-top: 18px;
}
}
</style>
[自定义适合大数据的select虚拟树选择组件]element puls的select和Tree V2 虚拟化树形控件 实现大数据 下拉选择,支持单选和多选
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 参考以下方法https://blog.csdn.net/w_quan/article/details/105711...
- vue+ element ui 树形控件tree实现单选功能 每天进步一点点~ 加油! 需求:1:父子节点不关联...
- template部分 一个三级嵌套就可以搞定 css部分 网上的办法大多都是直接在option上写,给option...