vue3 element ui 下拉树多选
时间: 2025-05-02 07:46:36 浏览: 36
### Vue3 Element Plus 下拉树组件实现多选功能
在 Vue3 中使用 Element Plus 的 `el-cascader` 或自定义封装的下拉树组件可以实现多选功能。以下是基于现有技术栈的一个解决方案。
#### 使用 Cascader 组件模拟多选效果
Element Plus 提供了级联选择器 (`el-cascader`),可以通过设置属性来支持多选模式。虽然它不是严格意义上的“下拉树”,但能够满足部分场景需求[^1]。
```vue
<template>
<el-cascader
v-model="selectedOptions"
:options="treeData"
multiple
clearable
collapse-tags
style="width: 300px;"
/>
</template>
<script setup>
import { ref } from 'vue';
const selectedOptions = ref([]);
const treeData = [
{
value: 'region1',
label: 'Region One',
children: [
{
value: 'city1',
label: 'City A'
},
{
value: 'city2',
label: 'City B'
}
]
},
{
value: 'region2',
label: 'Region Two',
children: [
{
value: 'city3',
label: 'City C'
},
{
value: 'city4',
label: 'City D'
}
]
}
];
</script>
```
上述代码展示了如何通过 `multiple` 属性启用多选功能,并利用 `collapse-tags` 来优化显示效果。
---
#### 封装 TSelect 组件实现虚拟列表多选
如果需要更复杂的交互逻辑(如全选、半选状态),则可参考引用中的 TSelect 组件设计思路[^2]。该方案适用于大规模数据集下的性能优化场景。
##### 自定义 Tree Select 组件示例
以下是一个简单的封装案例:
```vue
<template>
<div class="custom-tree-select">
<el-popover
placement="bottom-start"
title="请选择节点"
width="auto"
trigger="click"
@show="onPopoverShow"
v-model:visible="popoverVisible"
>
<template #reference>
<el-tag
v-for="(item, index) in selectedItems"
:key="index"
closable
size="small"
@close="handleTagClose(item)"
>
{{ item.label }}
</el-tag>
<span v-if="!selectedItems.length">请选择...</span>
</template>
<el-scrollbar max-height="200px">
<el-checkbox-group v-model="checkedKeys">
<ul>
<li v-for="node in filteredTreeData" :key="node.value">
<el-checkbox :label="node.value">{{ node.label }}</el-checkbox>
</li>
</ul>
</el-checkbox-group>
</el-scrollbar>
<div class="footer-actions">
<el-button type="text" @click="selectAllNodes">全选</el-button>
<el-button type="primary" @click="confirmSelection">确认</el-button>
</div>
</el-popover>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import { ElMessage } from 'element-plus';
// 数据源
const treeData = [
{ value: 'root1', label: 'Root Node 1' },
{ value: 'root2', label: 'Root Node 2' },
];
// Popover 控制变量
const popoverVisible = ref(false);
// 已选项管理
const checkedKeys = ref([]);
const selectedItems = computed(() =>
treeData.filter((node) => checkedKeys.value.includes(node.value))
);
function onPopoverShow() {
// 清理过滤条件或其他初始化操作
}
function handleTagClose(tagItem) {
const tagIndex = selectedItems.value.findIndex(
(item) => item.value === tagItem.value
);
if (tagIndex !== -1) {
checkedKeys.value.splice(tagIndex, 1);
}
}
function selectAllNodes() {
checkedKeys.value = treeData.map((node) => node.value);
}
function confirmSelection() {
popoverVisible.value = false;
ElMessage.success('已成功保存所选项');
}
</script>
<style scoped>
.custom-tree-select .footer-actions {
margin-top: 10px;
text-align: right;
}
</style>
```
此示例实现了基本的多选功能以及全选按钮的支持。
---
#### 性能优化建议
当面对大量节点时,推荐引入虚拟滚动机制以提升渲染效率。具体实现方式可通过第三方库(如 `vue-virtual-scroller`)完成,或者直接借鉴 TSelect 的设计理念。
---
阅读全文
相关推荐


