TreeSelect 树选择框
可以对树形结构数据进行选择。
基础用法
最简单的用法。
<template>
<tu-tree-select :data="treeData" placeholder="请输入" />
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-tree-select :data="treeData" placeholder="请输入" />
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
双向绑定
选中值支持双向绑定。
当前选择值:
<template>
<tu-tree-select placeholder="请输入" :data="treeData" v-model="value" />
<p>当前选择值:{{ value }}</p>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const value = ref();
</script>
<template>
<tu-tree-select placeholder="请输入" :data="treeData" v-model="value" />
<p>当前选择值:{{ value }}</p>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const value = ref();
</script>
设置 value 格式
labelInValue 为 true 时,value 格式为: { label: string, value: string }。
当前选择值:
<template>
<tu-tree-select
label-in-value
placeholder="请输入"
:data="treeData"
v-model="value"
/>
<p>当前选择值:{{ value }}</p>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const value = ref();
</script>
<template>
<tu-tree-select
label-in-value
placeholder="请输入"
:data="treeData"
v-model="value"
/>
<p>当前选择值:{{ value }}</p>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const value = ref();
</script>
动态加载
可以通过 loadMore 进行动态加载。此时可设置 isLeaf 来标示叶子节点。
<template>
<tu-tree-select :data="treeData" placeholder="请输入" :load-more="loadMore" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = ref([
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
]);
const loadMore = (nodeData) => {
const { title, key } = nodeData;
const children = [
{
title: `${title}-1`,
key: `${key}-1`
},
{
title: `${title}-2`,
key: `${key}-2`
}
];
return new Promise((resolve) => {
setTimeout(() => {
nodeData.children = children;
resolve();
}, 1000);
});
};
</script>
<template>
<tu-tree-select :data="treeData" placeholder="请输入" :load-more="loadMore" />
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = ref([
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
]);
const loadMore = (nodeData) => {
const { title, key } = nodeData;
const children = [
{
title: `${title}-1`,
key: `${key}-1`
},
{
title: `${title}-2`,
key: `${key}-2`
}
];
return new Promise((resolve) => {
setTimeout(() => {
nodeData.children = children;
resolve();
}, 1000);
});
};
</script>
搜索
设置 allow-search 为 true 启用搜索功能。动态加载时候只能在已加载数据中进行搜索。默认的关键字搜索是从value字段匹配。也可以传入 filterTreeNode自定义过滤方式。
基本搜索
自定义搜索
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>基本搜索</p>
<tu-tree-select
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>自定义搜索</p>
<tu-tree-select
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
:filter-tree-node="
(searchValue, nodeData) =>
nodeData.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1
"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>基本搜索</p>
<tu-tree-select
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>自定义搜索</p>
<tu-tree-select
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
:filter-tree-node="
(searchValue, nodeData) =>
nodeData.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1
"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
远程搜索
监听 search 事件,在事件处理函数中获取数据并更新 treeData。 自定义搜索逻辑时,建议关闭内部过滤逻(disable-filter 为 true ),以免影响自定义结果。
<template>
<tu-tree-select
allow-search
allow-clear
disable-filter
placeholder="请输入"
:loading="loading"
:data="treeData"
@search="onSearch"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const defaultTreeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const loading = ref(false);
const treeData = ref(defaultTreeData);
const onSearch = (searchKey) => {
loading.value = true;
setTimeout(() => {
loading.value = false;
treeData.value = searchData(searchKey);
}, 800);
};
const searchData = (keyword) => {
const loop = (data) => {
const result = [];
data.forEach((item) => {
if (item.title.toLowerCase().indexOf(keyword.toLowerCase()) > -1) {
result.push({ ...item });
} else if (item.children) {
const filterData = loop(item.children);
if (filterData.length) {
result.push({
...item,
children: filterData
});
}
}
});
return result;
};
return loop(defaultTreeData);
};
</script>
<template>
<tu-tree-select
allow-search
allow-clear
disable-filter
placeholder="请输入"
:loading="loading"
:data="treeData"
@search="onSearch"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const defaultTreeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const loading = ref(false);
const treeData = ref(defaultTreeData);
const onSearch = (searchKey) => {
loading.value = true;
setTimeout(() => {
loading.value = false;
treeData.value = searchData(searchKey);
}, 800);
};
const searchData = (keyword) => {
const loop = (data) => {
const result = [];
data.forEach((item) => {
if (item.title.toLowerCase().indexOf(keyword.toLowerCase()) > -1) {
result.push({ ...item });
} else if (item.children) {
const filterData = loop(item.children);
if (filterData.length) {
result.push({
...item,
children: filterData
});
}
}
});
return result;
};
return loop(defaultTreeData);
};
</script>
多选
多选。
基础多选
请输入
最多显示2个标签
请输入
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>基础多选</p>
<tu-tree-select
multiple
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>最多显示2个标签</p>
<tu-tree-select
multiple
allow-search
allow-clear
placeholder="请输入"
:max-tag-count="2"
:data="treeData"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>基础多选</p>
<tu-tree-select
multiple
allow-search
allow-clear
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>最多显示2个标签</p>
<tu-tree-select
multiple
allow-search
allow-clear
placeholder="请输入"
:max-tag-count="2"
:data="treeData"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
复选框多选
可以通过设置 treeCheckable 属性开启复选框勾选。
复选框多选
请输入
父子不关联
请输入
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>复选框多选</p>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>父子不关联</p>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
tree-check-strictly
placeholder="请输入"
:data="treeData"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-row :gutter="20">
<tu-col :span="12">
<p>复选框多选</p>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
placeholder="请输入"
:data="treeData"
/>
</tu-col>
<tu-col :span="12">
<p>父子不关联</p>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
tree-check-strictly
placeholder="请输入"
:data="treeData"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
定制回填方式
可以通过 treeCheckStrategy 属性定制回填方式。
请输入
<template>
<tu-radio-group
class="mb-2"
type="button"
v-model="treeCheckedStrategy"
@change="
() => {
selected = [];
}
"
>
<tu-radio label="all">所有节点</tu-radio>
<tu-radio label="parent">父节点</tu-radio>
<tu-radio label="child">子节点</tu-radio>
</tu-radio-group>
<tu-tree-select
v-model="selected"
allow-search
allow-clear
tree-checkable
placeholder="请输入"
:tree-checked-strategy="treeCheckedStrategy"
:data="treeData"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const selected = ref([]);
const treeCheckedStrategy = ref('all');
</script>
<template>
<tu-radio-group
class="mb-2"
type="button"
v-model="treeCheckedStrategy"
@change="
() => {
selected = [];
}
"
>
<tu-radio label="all">所有节点</tu-radio>
<tu-radio label="parent">父节点</tu-radio>
<tu-radio label="child">子节点</tu-radio>
</tu-radio-group>
<tu-tree-select
v-model="selected"
allow-search
allow-clear
tree-checkable
placeholder="请输入"
:tree-checked-strategy="treeCheckedStrategy"
:data="treeData"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const selected = ref([]);
const treeCheckedStrategy = ref('all');
</script>
下拉框的页头和页脚
自定义树选择下拉框的页头和页脚。
请输入
<template>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
v-model="checkedKeys"
:data="treeData"
placeholder="请输入"
>
<template #header>
<div style="padding: 6px 12px">
<tu-checkbox
v-model="checkAll"
:indeterminate="indeterminate"
@change="handleCheckAll"
>
全选
</tu-checkbox>
</div>
</template>
<template #footer>
<div style="padding: 6px 12px; text-align: right">
已选择{{ checkedKeys.length }}个节点
</div>
</template>
</tu-tree-select>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const allCheckedKeys = ['1', '1-1', '1-1-1', '1-1-2', '1-2', '1-2-1'];
const checkAll = ref(false);
const indeterminate = ref(false);
const checkedKeys = ref([]);
watch(checkedKeys, (val) => {
if (val.length === 0) {
checkAll.value = false;
indeterminate.value = false;
} else if (val.length === allCheckedKeys.length) {
checkAll.value = true;
indeterminate.value = false;
} else {
indeterminate.value = true;
}
});
const handleCheckAll = (value: boolean) => {
checkedKeys.value = value ? allCheckedKeys : [];
};
</script>
<template>
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
v-model="checkedKeys"
:data="treeData"
placeholder="请输入"
>
<template #header>
<div style="padding: 6px 12px">
<tu-checkbox
v-model="checkAll"
:indeterminate="indeterminate"
@change="handleCheckAll"
>
全选
</tu-checkbox>
</div>
</template>
<template #footer>
<div style="padding: 6px 12px; text-align: right">
已选择{{ checkedKeys.length }}个节点
</div>
</template>
</tu-tree-select>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const allCheckedKeys = ['1', '1-1', '1-1-1', '1-1-2', '1-2', '1-2-1'];
const checkAll = ref(false);
const indeterminate = ref(false);
const checkedKeys = ref([]);
watch(checkedKeys, (val) => {
if (val.length === 0) {
checkAll.value = false;
indeterminate.value = false;
} else if (val.length === allCheckedKeys.length) {
checkAll.value = true;
indeterminate.value = false;
} else {
indeterminate.value = true;
}
});
const handleCheckAll = (value: boolean) => {
checkedKeys.value = value ? allCheckedKeys : [];
};
</script>
自定义触发元素
自定义触发元素。
<template>
<tu-tree-select :data="treeData" @change="onChange">
<template #trigger>
<tu-button>已选择 {{ selected }}</tu-button>
</template>
</tu-tree-select>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const selected = ref('');
const onChange = (value) => {
selected.value = value;
};
</script>
<template>
<tu-tree-select :data="treeData" @change="onChange">
<template #trigger>
<tu-button>已选择 {{ selected }}</tu-button>
</template>
</tu-tree-select>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const selected = ref('');
const onChange = (value) => {
selected.value = value;
};
</script>
控制下拉框的展开收起
通过 popupVisible (支持 v-model) 控制下拉框的展开和收起。
<template>
<tu-button class="mb-2" @click="toggle">切换</tu-button>
<tu-tree-select
allow-clear
:popup-visible="popupVisible"
:data="treeData"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const popupVisible = ref(false);
const toggle = () => {
popupVisible.value = !popupVisible.value;
};
</script>
<template>
<tu-button class="mb-2" @click="toggle">切换</tu-button>
<tu-tree-select
allow-clear
:popup-visible="popupVisible"
:data="treeData"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
disabled: true,
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const popupVisible = ref(false);
const toggle = () => {
popupVisible.value = !popupVisible.value;
};
</script>
自定义 TreeData 的字段名称
通过 fieldNames 字段可以自定义 TreeData 的字段名。
<template>
<tu-tree-select
:data="treeData"
:fieldNames="{
key: 'value',
title: 'label',
children: 'options'
}"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const treeData = [
{
label: '主干 1',
value: '1',
options: [
{
label: '分支 1-1',
value: '1-1',
options: [
{
label: '叶子 1-1-1',
value: '1-1-1'
},
{
label: '叶子 1-1-2',
value: '1-1-2'
}
]
},
{
label: '分支 1-2',
value: '1-2',
options: [
{
label: '叶子 1-2-1',
value: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-tree-select
:data="treeData"
:fieldNames="{
key: 'value',
title: 'label',
children: 'options'
}"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const treeData = [
{
label: '主干 1',
value: '1',
options: [
{
label: '分支 1-1',
value: '1-1',
options: [
{
label: '叶子 1-1-1',
value: '1-1-1'
},
{
label: '叶子 1-1-2',
value: '1-1-2'
}
]
},
{
label: '分支 1-2',
value: '1-2',
options: [
{
label: '叶子 1-2-1',
value: '1-2-1'
}
]
}
]
}
];
</script>
虚拟列表
通过指定 treeProps.virtualListProps 来开启虚拟列表,在大量数据时获得高性能表现。
<template>
<tu-tree-select
:data="treeData"
:treeProps="{
virtualListProps: {
height: 300
}
}"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const loop = (path = '1', level = 2) => {
const list = [];
for (let i = 0; i < 10; i += 1) {
const key = `${path}-${i + 1}`;
const treeNode = {
title: key,
key
};
if (level > 0) {
treeNode.children = loop(key, level - 1);
}
list.push(treeNode);
}
return list;
};
const treeData = loop();
</script>
<template>
<tu-tree-select
:data="treeData"
:treeProps="{
virtualListProps: {
height: 300
}
}"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const loop = (path = '1', level = 2) => {
const list = [];
for (let i = 0; i < 10; i += 1) {
const key = `${path}-${i + 1}`;
const treeNode = {
title: key,
key
};
if (level > 0) {
treeNode.children = loop(key, level - 1);
}
list.push(treeNode);
}
return list;
};
const treeData = loop();
</script>
回退选项
使用 fallback-option 自定义找不到选项的值的显示效果,默认找不到选项就展示值本身。用户可以将其设定为 false 来隐藏那些没有匹配到节点数据的值。
fallback
<template>
<tu-tree-select
defaultValue="0"
:fallback-option="
(key) => {
return { key, title: 'fallback' };
}
"
:data="treeData"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
<template>
<tu-tree-select
defaultValue="0"
:fallback-option="
(key) => {
return { key, title: 'fallback' };
}
"
:data="treeData"
placeholder="请输入"
/>
</template>
<script lang="ts" setup>
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
</script>
不同尺寸
设置 size 可以使用四种尺寸(small, default, large, huge)的选择器。
请输入
<template>
<tu-radio-group class="mb-2" v-model="size" type="button">
<tu-radio label="mini">超小</tu-radio>
<tu-radio label="small">较小</tu-radio>
<tu-radio label="medium">中等</tu-radio>
<tu-radio label="large">较大</tu-radio>
</tu-radio-group>
<tu-row :gutter="20">
<tu-col :span="12">
<tu-tree-select :size="size" :data="treeData" placeholder="请输入" />
</tu-col>
<tu-col :span="12">
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
:size="size"
:data="treeData"
placeholder="请输入"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const size = ref('medium');
</script>
<template>
<tu-radio-group class="mb-2" v-model="size" type="button">
<tu-radio label="mini">超小</tu-radio>
<tu-radio label="small">较小</tu-radio>
<tu-radio label="medium">中等</tu-radio>
<tu-radio label="large">较大</tu-radio>
</tu-radio-group>
<tu-row :gutter="20">
<tu-col :span="12">
<tu-tree-select :size="size" :data="treeData" placeholder="请输入" />
</tu-col>
<tu-col :span="12">
<tu-tree-select
multiple
allow-search
allow-clear
tree-checkable
:size="size"
:data="treeData"
placeholder="请输入"
/>
</tu-col>
</tu-row>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const treeData = [
{
title: '主干 1',
key: '1',
children: [
{
title: '分支 1-1',
key: '1-1',
children: [
{
title: '叶子 1-1-1',
key: '1-1-1'
},
{
title: '叶子 1-1-2',
key: '1-1-2'
}
]
},
{
title: '分支 1-2',
key: '1-2',
children: [
{
title: '叶子 1-2-1',
key: '1-2-1'
}
]
}
]
}
];
const size = ref('medium');
</script>
TreeSelect API
TreeSelect Attributes
参数名 | 描述 | 类型 | 默认值 |
---|---|---|---|
disabled | 是否禁用 | Boolean | false |
loading | 是否为加载中状态 | Boolean | false |
size | 选择框的大小 | String | medium |
border | 是否显示边框 | Boolean | true |
allow-search | 是否允许搜索 | Boolean Object | false |
allow-clear | 是否允许清除 | Boolean | false |
placeholder | 提示文案 | String | - |
max-tag-count | 最多显示的标签数量,仅在多选模式有效 | Number | - |
multiple | 是否支持多选 | Boolean | false |
default-value | 默认值 | String Number Array | - |
model-value / v-model | 绑定值 | String Number Array | - |
field-names | 指定节点数据中的字段名 | Object | - |
data | 数据 | Array | [] |
label-in-value | 设置value格式。默认是string,设置为true时候,value格式为:'{ label: string, value: string }' | Boolean | false |
tree-checkable | 是否展示复选框 | Boolean | false |
tree-check-strictly | 父子节点是否关联 | Boolean | false |
tree-checked-strategy | 定制回显方式 | String | all |
tree-props | 可以接受所有 Tree 组件的Props | Object | - |
trigger-props | 可以接受所有 Trigger 组件的Props | Object | - |
popup-visible / v-model | 弹出框是否可见 | Boolean | - |
default-popup-visible | 默认弹出框是否可见 | Boolean | false |
dropdown-style | 下拉框样式 | Object | - |
dropdown-class-name | 下拉框样式 class | String Array | - |
filter-tree-node | 自定义节点过滤函数 | Function | - |
load-more | 动态加载数据 | Function | - |
disable-filter | 禁用内部过滤逻辑 | Boolean | false |
popup-container | 弹出框的挂载容器 | String HTMLElement | - |
fallback-option | 为 value 中找不到匹配项的 key 定义节点数据 | Boolean Function | true |
selectable | 设置可选择的节点,默认全部可选 | Boolean | true |
scrollbar | 是否开启虚拟滚动条 | Boolean Object | true |
show-header-on-empty | 空状态时是否显示header | Boolean | false |
show-footer-on-empty | 空状态时是否显示footer | Boolean | false |
TreeSelect Events
事件名 | 描述 | 参数 |
---|---|---|
change | 值改变时触发 | Function |
popup-visible-change | 下拉框显示状态改变时触发 | Function |
search | 搜索值变化时触发 | Function |
clear | 点击清除时触发 | - |
TreeSelect Slots
参数名 | 描述 | 参数 |
---|---|---|
trigger | 自定义触发元素 | - |
prefix | 前缀 | - |
label | 自定义选择框显示 | data: mixed |
header | 自定义下拉框页头 | - |
loader | 定制加载中显示的内容 | - |
empty | 定制空数据展示 | - |
footer | 自定义下拉框页脚 | - |
tree-slot-extra | 定制 tree 组件的渲染额外节点内容 | - |
tree-slot-title | 定制 tree 组件的节点标题 | - |
tree-slot-icon | 定制 tree 组件的节点图标 | node: TreeNodeData |
tree-slot-switcher-icon | 定制 tree 组件的 switcher 图标 | - |