FitsTreeSelect 树形选择
# FitsTreeSelect 树形选择
# 基本用法
基础的树形筛选组件展示。当节点数据过长时,会通过滚动条的形式进行展示。默认只能选择叶子节点的数据。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
select: {
clearable: true,
},
tree: {
nodeKey: "id",
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
},
}))
</script>
# 选择任意级别
通过设置 tree.checkStrictly=true
,任何节点都可以被选择,否则只有子节点可被选择。开启后通过点击箭头图标进行展开/收缩。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
select: {
clearable: true,
},
tree: {
nodeKey: "id",
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
checkStrictly: true
},
}))
</script>
# 禁用状态
禁用整个树形筛选组件。设置 select.disabled = true
,禁用与组件的交互。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
select: {
disabled: true,
},
tree: {
nodeKey: "id",
defaultExpandAll: false,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
}
}))
</script>
# 禁用复选框
设置 tree.showCheckbox
启用节点复选框,并为 tree.data
中的选项设置 disabled = true
,相应的复选框已禁用,不能点击。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
defaultExpandAll: false,
showCheckbox: true,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
disabled: true
},
],
},
],
},
{
id: '21',
label: '研发部',
disabled: true,
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
}
}))
</script>
# 过滤节点
设置 input.show = true
开启内部过滤输入框。 默认情况下,TreeSelect 会找出所有 label
属性包含输入值的选项。
<template>
<fits-tree-select :options="state1" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state1 = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
defaultExpandAll: false,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
},
}))
</script>
# 自定义过滤方法
如果希望使用其他的搜索逻辑,可以通过设置 tree.filterNodeMethod
来实现。 filterNodeMethod
为一个函数,它会在输入值发生变化时调用,参数为当前输入值。此范例演示了 '输入什么就不返回什么' 的功能。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
import type { TreeNodeData } from 'element-plus/es/components/tree/src/tree.type'
const state = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
defaultExpandAll: false,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
filterNodeMethod: (value: string, data: TreeNodeData, node: any) => {
if (!value) return true
return node.label.indexOf(value) === -1
}
},
}))
</script>
# 默认选中
通过传递 modelValue
属性可以给下拉树筛选组件传递默认值,该值必须跟 tree.nodeKey
指定的属性值对应。
<template>
<fits-tree-select :options="state" modelValue="9" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
select: {
clearable: true,
placeholder: '请选择'
},
input: {
clearable: true,
},
tree: {
nodeKey: "id",
defaultExpandAll: false,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
}
}))
</script>
# 展开所有节点、可拖拽
通过设置 tree.defaultExpandAll=true
可以默认展开所有节点。通过设置 tree.draggable=true
可以开启树节点拖拽。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
defaultExpandAll: true,
draggable: true,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
}
}))
</script>
# 自定义节点内容
通过设置 tree.renderContent
渲染函数,该函数返回需要的节点区内容即可。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
defaultExpandAll: true,
expandOnClickNode: false,
data: [
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
],
renderContent,
}
}))
const append = (data: any) => {
let id = 1000
const newChild = { id: id++, label: 'testtest', children: [] }
if (!data.children) {
data.children = []
}
data.children.push(newChild)
state.tree.data = [...state.tree.data]
}
const remove = (node: any, data: any) => {
const parent = node.parent
const children: any[] = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
state.tree.data = [...state.tree.data]
}
function renderContent(
h: any,
{
node,
data,
store,
}: any
) {
return h(
'span',
{
class: 'custom-tree-node',
},
h('span', null, node.label),
h(
'div',
{
style: 'display: flex'
},
h(
'div',
{
onClick: (e: any) => {
e.stopPropagation();
append(data)
},
class: 'operation'
},
'Append '
),
h(
'div',
{
style: 'margin-left: 8px',
class: 'operation',
onClick: (e: any) => {
e.stopPropagation();
remove(node, data)
},
},
'Delete'
)
)
)
}
</script>
<style lang="scss">
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.operation {
color: #007dff;
display: inline-block;
position: relative;
}
.operation::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 1px;
bottom: 0;
left: 0;
background-color: #007dff;
transform-origin: bottom right;
transition: transform 0.15s ease-out;
}
.operation:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
}
</style>
# 动态加载节点数据
动态加载数据仅当 tree.lazy=true
时有效。并通过 tree.load
传递一个函数,参数为 node
和 resolve
, node
为当前点击的节点,resolve
为数据加载完成的回调。
<template>
<fits-tree-select :options="state" />
</template>
<script lang="ts" setup>
import type Node from 'element-plus/es/components/tree/src/model/node'
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const state = reactive(new FitsTreeSelectModel({
tree: {
nodeKey: "id",
load: loadNode,
lazy: true,
}
}))
let count = 0
function loadNode(node: Node, resolve: any) {
if (node.level === 0) {
return resolve([{ label: 'Root1', id: count++ }, { label: 'Root2', id: count++ }])
}
if (node.level > 3) {
return resolve([])
}
setTimeout(() => {
let data: any = []
data = [
{
id: count,
label: `children${count++}`,
},
{
id: count,
label: `children${count++}`,
},
]
resolve(data)
}, 500)
}
</script>
# 多选节点
通过配置 tree.showCheckbox=true
和 select.multiple=true
开启树节点的复选框按钮。
<template>
<div class="innerBox">
<div>
默认值
<div class="describe">通过设置 modelValue 传递一个由节点的key组成的数组,设置多选默认值</div>
</div>
<fits-tree-select :options="state1" :modelValue="value" />
</div>
<div class="innerBox">
<div>
多选项省略,以数字形式展示
<div class="describe">通过设置 select.collapseTags = true,折叠多选项内容</div>
</div>
<fits-tree-select :options="state2" />
</div>
<div class="innerBox">
<div>
鼠标悬浮文字出现多选项标签
<div class="describe">通过设置 select.collapseTags = true 和 select.collapseTagsTooltip = true,鼠标悬浮在数字上时,显示折叠项
</div>
</div>
<fits-tree-select :options="state3" />
</div>
<div class="innerBox">
<div>
点击节点时选中
<div class="describe">设置 tree.checkOnClickNode = true ,点击节点时勾选上,默认通过点击复选框才能勾选。</div>
</div>
<fits-tree-select :options="state4" />
</div>
</template>
<script lang="ts" setup>
import { FitsTreeSelect } from '@/fits-components';
import { FitsTreeSelectModel } from '@/fits-components/type';
const value = ref(['9', '11'])
const data = reactive([
{
id: '1',
label: '总经办',
children: [
{
id: '4',
label: '业务部',
children: [
{
id: '9',
label: '业务A部'
},
{
id: '11',
label: '业务B部',
},
],
},
],
},
{
id: '21',
label: '研发部',
children: [
{
id: '5',
label: '研发1部',
},
{
id: '6',
label: '研发2部',
},
],
},
{
id: '3',
label: '财务部',
children: [
{
id: '7',
label: '财务1部',
},
{
id: '8',
label: '财务2部',
},
],
},
])
const state1 = reactive(new FitsTreeSelectModel({
select: {
multiple: true,
},
tree: {
nodeKey: "id",
highlightCurrent: false,
showCheckbox: true,
data
},
}))
const state2 = reactive(new FitsTreeSelectModel({
select: {
multiple: true,
collapseTags: true,
},
tree: {
nodeKey: "id",
highlightCurrent: false,
showCheckbox: true,
data
},
}))
const state3 = reactive(new FitsTreeSelectModel({
select: {
multiple: true,
collapseTags: true,
collapseTagsTooltip: true
},
tree: {
nodeKey: "id",
highlightCurrent: false,
showCheckbox: true,
data
},
}))
const state4 = reactive(new FitsTreeSelectModel({
select: {
multiple: true,
collapseTags: true,
collapseTagsTooltip: true
},
tree: {
nodeKey: "id",
showCheckbox: true,
checkOnClickNode: true,
data
},
}))
</script>
<style lang="scss" scoped>
.innerBox {
margin-top: 16px;
.describe {
font-size: 14px;
margin: 4px 0;
}
}
</style>
# FitsTreeSelectModel属性
属性 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
input | 内部过滤框配置 | ElInputopen in new window | 非必填 | - |
tree | 树配置 | TreeComponentPropsopen in new window | 必填 | - |
select | 选择器配置 | FitsSelectProps | 非必填 | - |
# FitsSelectProps属性
属性 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
disabled | 是否禁用树下拉筛选组件 | boolean | - | false |
size | 系统配置 | string | large / default / small | default |
clearable | 是否可以清空选项 | boolean | - | false |
effect | 下拉框的主题 | string | dark / light | light |
placeholder | 占位文字 | string | - | 请选择 |
popperClass | 下拉框的自定义类名 | string | - | - |
teleported | 是否将下拉框插入至body 元素 | boolean | - | true |
persistent | 当下拉选择器未被激活并且persistent 设置为false ,选择器会被删除 | boolean | - | true |
clearIcon | 自定义清除图标组件 | string / SvgComponent | - | CircleClose |
fitInputWidth | 下拉框的宽度是否与选择器相同 | boolean | - | true |
suffixIcon | 自定义后缀图标组件 | string / SvgComponent | - | CaretTop |
validateEvent | 输入时是否触发表单校验 | boolean | - | true |
multiple | 是否多选 | boolean | - | false |
collapseTags | 多选时是否将选中值按文字的形式展示 | boolean | - | false |
collapseTagsTooltip | 当鼠标悬停于折叠标签的文本时,是否显示所有选中的标签。要使用此属性,collapseTags 属性必须设定为true | boolean | - | false |
# 方法
获取组件实例的 treeRef
对象,其中包含树组件的所有方法。 参考el-treeopen in new window
# 事件
事件名 | 说明 | 回调参数 |
---|---|---|
update:modelValue | 当选中值发生变化时触发 | 一个参数,为被选中节点的id 。类型为字符串,如果多选则为字符串数组。 |
# 插槽
暂无可用的插槽