Tree 树形控件

展示组织架构、文件目录、分类列表等层级数据,支持单选多选、搜索、拖拽。

何时使用

  • 需要展示树形层级结构时。

基础用法

默认为单选模式,每一级菜单项均可选择。

<script setup lang="ts">
import { ref } from "vue";
import { Tree } from "@reglow/reui";

const value = ref("");
const treeData = [
  {
    label: "亚洲",
    value: "Asia",
    key: "0",
    children: [
      {
        label: "中国",
        value: "China",
        key: "0-0",
        children: [
          { label: "北京", value: "Beijing", key: "0-0-0" },
          { label: "上海", value: "Shanghai", key: "0-0-1" },
        ],
      },
      { label: "日本", value: "Japan", key: "0-1" },
    ],
  },
  {
    label: "北美洲",
    value: "NA",
    key: "1",
    children: [
      { label: "美国", value: "USA", key: "1-0" },
      { label: "加拿大", value: "Canada", key: "1-1" },
    ],
  },
];
</script>

<template>
  <Tree v-model="value" :tree-data="treeData" class="w-[260px]" />
</template>
文件夹 2

导入

import { Tree } from "@reglow/reui";
import type { TreeNodeData } from "@reglow/reui";

更多示例

多选

设置 multiple 进行多选。多选时所有子项都被选择时自动勾选父项。

<script setup lang="ts">
import { ref } from "vue";

const value = ref<string[]>([]);
</script>

<template>
  <Tree v-model="value" :tree-data="treeData" multiple class="w-[260px]" />
</template>

可搜索

通过设置 filterTreeNode 属性开启搜索功能。

<template>
  <Tree
    :tree-data="treeData"
    filter-tree-node
    class="w-[260px] h-[400px]"
  />
</template>

仅展示匹配结果

设置 showFilteredOnly 只展示搜索匹配的节点。

<template>
  <Tree
    :tree-data="treeData"
    filter-tree-node
    show-filtered-only
    class="w-[260px] h-[400px]"
  />
</template>

默认展开

<template>
  <!-- 默认展开所有 -->
  <Tree :tree-data="treeData" default-expand-all class="w-[260px]" />

  <!-- 展开指定节点 -->
  <Tree
    :tree-data="treeData"
    :default-expanded-keys="['0', '0-0']"
    class="w-[260px]"
  />
</template>

展开受控

<script setup lang="ts">
import { ref } from "vue";

const expandedKeys = ref(["0", "0-0"]);
</script>

<template>
  <Tree
    v-model:expanded-keys="expandedKeys"
    :tree-data="treeData"
    class="w-[260px]"
  />
</template>

连接线

通过 showLine 设置节点之间的连接线。

<template>
  <Tree :tree-data="treeData" show-line class="w-[260px]" />
</template>

目录树模式

通过 directory 属性显示为目录树模式,自带目录图标。

<template>
  <Tree :tree-data="treeData" directory class="w-[260px]" />
</template>

自定义图标

通过节点的 icon 属性添加自定义图标。

<script setup lang="ts">
import { h } from "vue";
import { Tree } from "@reglow/reui";
import { MapPin } from "lucide-vue-next";

const treeData = [
  {
    label: "Asia",
    value: "Asia",
    key: "0",
    icon: h(MapPin),
    children: [
      { label: "China", value: "China", key: "0-0" },
    ],
  },
];
</script>

<template>
  <Tree :tree-data="treeData" class="w-[260px]" />
</template>

自定义节点内容

通过 #label slot 自定义节点标签。

<template>
  <Tree :tree-data="treeData" class="w-[260px]">
    <template #label="{ node, level }">
      <span>{{ node.label }}</span>
      <span v-if="node.children" class="text-xs text-muted-foreground ml-1">
        ({{ node.children.length }})
      </span>
    </template>
  </Tree>
</template>

禁用

<script setup lang="ts">
const treeData = [
  {
    label: "亚洲",
    key: "0",
    disabled: true,
    children: [{ label: "中国", key: "0-0" }],
  },
];
</script>

<template>
  <Tree :tree-data="treeData" class="w-[260px]" />
</template>

节点选中关系

多选时设置 checkRelationunRelated,节点间选中互不影响。

<template>
  <Tree
    v-model="value"
    :tree-data="treeData"
    multiple
    check-relation="unRelated"
    class="w-[260px]"
  />
</template>

仅返回叶子节点

设置 leafOnly 使 onChange 回调仅返回叶子节点。

<template>
  <Tree
    v-model="value"
    :tree-data="treeData"
    multiple
    leaf-only
    class="w-[260px]"
  />
</template>

异步加载

通过 loadData 动态加载数据,需要在数据中传入 isLeaf 标明叶子节点。

<script setup lang="ts">
const treeData = [
  { label: "加载更多", value: "0", key: "0", isLeaf: false },
  { label: "叶子节点", value: "1", key: "1", isLeaf: true },
];

const loadData = async (node: any) => {
  // 模拟异步请求
  await new Promise((resolve) => setTimeout(resolve, 1000));
  node.children = [
    { label: "子节点1", value: `${node.key}-0`, key: `${node.key}-0`, isLeaf: true },
    { label: "子节点2", value: `${node.key}-1`, key: `${node.key}-1`, isLeaf: true },
  ];
};
</script>

<template>
  <Tree :tree-data="treeData" :load-data="loadData" class="w-[260px]" />
</template>

受控

<script setup lang="ts">
import { ref } from "vue";

const value = ref("Shanghai");
</script>

<template>
  <Tree v-model="value" :tree-data="treeData" class="w-[260px]" />
</template>

API

Props

属性类型默认值说明
treeDataTreeNodeData[][]树数据
modelValuestring | number | (string | number)[]-当前选中值(v-model)
defaultValuestring | number | (string | number)[]-默认选中值
multiplebooleanfalse是否多选
disabledbooleanfalse是否禁用
defaultExpandAllbooleanfalse默认展开所有
expandAllbooleanfalse展开所有(数据更新时生效)
defaultExpandedKeysstring[]-默认展开的 key
expandedKeysstring[]-展开的 key(v-model)
autoExpandParentbooleanfalse自动展开父节点
showLinebooleanfalse是否显示连接线
blockNodebooleantrue节点占据整行
directorybooleanfalse目录树模式
filterTreeNodeboolean | ((input, node) => boolean)false开启搜索
searchPlaceholderstring搜索搜索框占位文字
showFilteredOnlybooleanfalse仅展示匹配节点
treeNodeFilterPropstringlabel搜索匹配属性
checkRelationrelated | unRelatedrelated节点选中关系
leafOnlybooleanfalse仅返回叶子节点
loadData(node) => Promise<void>-异步加载
draggablebooleanfalse是否可拖拽
classstring-附加类名

Events

事件说明回调参数
change选中变化(value, node)
select选中节点(node, selected: boolean)
expand展开/收起(keys, node)
search搜索(value, filteredKeys)

Slots

名称说明参数
label自定义节点标签{ node, level }
icon自定义图标{ node, level, expanded }
trailing后置内容{ node, level, expanded }

类型

TreeNodeData:

属性类型默认值说明
labelstring-标签
valuestring | number-
keystring用 value唯一标识
childrenTreeNodeData[]-子节点
disabledbooleanfalse是否禁用
isLeafboolean-是否叶子节点
iconVNode-自定义图标
defaultExpandedbooleanfalse是否默认展开
extrastring-副文本

多选行为

checkRelation说明
related父子关联:选中父节点自动选中所有子节点,子节点全选时自动勾选父节点(含半选状态)
unRelated父子不关联:各节点选中状态互不影响

国际化

搜索占位文案默认跟随全局语言(zh-CN / zh-TW / en-US)。