安裝
Terminal
pnpm dlx shadcn-vue add @admin/treeimport { AdminTree, AdminTreeItem } from '@/components/admin/tree'用法
<script setup lang="ts">import { ref } from 'vue'import { AdminTree, AdminTreeItem } from '@/components/admin/tree'interface Node { id: string label: string children?: Node[]}const items: Node[] = [ { id: '1', label: '標題名稱', children: [ { id: '1-1', label: '項目名稱' }, { id: '1-2', label: '項目名稱' }, { id: '1-3', label: '標題名稱', children: [ { id: '1-3-1', label: '項目名稱' }, { id: '1-3-2', label: '項目名稱' }, { id: '1-3-3', label: '標題名稱', children: [ { id: '1-3-3-1', label: '項目名稱' }, { id: '1-3-3-2', label: '項目名稱' }, { id: '1-3-3-3', label: '標題名稱', children: [{ id: '1-3-3-3-1', label: '項目名稱' }] } ] } ] } ] }]const expanded = ref<string[]>(['1', '1-3', '1-3-3'])const selected = ref<Node | undefined>()</script><template> <admin-tree v-model="selected" v-model:expanded="expanded" class="w-[18rem] border border-text-30" :get-key="(node: Node) => node.id" :items > <template #default="{ flattenItems }"> <admin-tree-item v-for="item in flattenItems" :key="item._id" v-bind="item.bind" :has-children="item.hasChildren" > {{ item.value.label }} </admin-tree-item> </template> </admin-tree></template>場景
多選與 Checkbox
<script setup lang="ts">import { IconCaretDownFilled, IconCaretRightFilled } from '@tabler/icons-vue'import { ref } from 'vue'import { AdminCheckbox, AdminCheckboxInput } from '@/components/admin/checkbox'import { AdminTree, AdminTreeItem } from '@/components/admin/tree'interface Node { id: string label: string children?: Node[]}const items: Node[] = [ { id: 'a', label: '標題名稱', children: [ { id: 'a-1', label: '項目名稱' }, { id: 'a-2', label: '項目名稱' } ] }, { id: 'b', label: '標題名稱', children: [ { id: 'b-1', label: '項目名稱' }, { id: 'b-2', label: '項目名稱' }, { id: 'b-3', label: '標題名稱', children: [ { id: 'b-3-1', label: '項目名稱' }, { id: 'b-3-2', label: '項目名稱' } ] } ] }]const expanded = ref<string[]>(['a', 'b', 'b-3'])const selected = ref<Node[]>([])</script><template> <admin-tree v-model="selected" v-model:expanded="expanded" class="w-[18rem] border border-text-30" bubble-select multiple propagate-select :get-key="(node: Node) => node.id" :items > <template #default="{ flattenItems }"> <admin-tree-item v-for="item in flattenItems" :key="item._id" v-bind="item.bind" :has-children="item.hasChildren" @select="(ev) => item.hasChildren && ev.preventDefault()" > <template #prefix="{ isSelected, isIndeterminate, isExpanded, hasChildren, handleSelect }"> <admin-checkbox class="shrink-0 cursor-pointer" @click.stop="handleSelect()"> <admin-checkbox-input class="pointer-events-none" tabindex="-1" :model-value="isIndeterminate ? 'indeterminate' : isSelected" /> </admin-checkbox> <icon-caret-down-filled v-if="hasChildren && isExpanded" class="size-4 shrink-0 text-text-90" /> <icon-caret-right-filled v-else-if="hasChildren" class="size-4 shrink-0 text-text-90" /> </template> {{ item.value.label }} </admin-tree-item> </template> </admin-tree></template>API 參考
組成
<template> <admin-tree v-slot="{ flattenItems }" :get-key="(item) => item.id" :items="data"> <admin-tree-item v-for="item in flattenItems" :key="item._id" v-bind="item.bind" :has-children="item.hasChildren" > {{ item.value.label }} </admin-tree-item> </admin-tree></template>admin-tree
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
class | ClassValue | — | 根元素之自訂 class |
modelValue | (Multiple extends true ? TValue[] : TValue) | undefined | — | The controlled value of the tree. Can be binded with `v-model`. |
defaultValue | (Multiple extends true ? TValue[] : TValue) | undefined | — | The value of the tree when initially rendered. Use when you do not need to control the state of the tree |
items | TItem[] | undefined | — | List of items |
expanded | string[] | undefined | — | The controlled value of the expanded item. Can be binded with `v-model`. |
defaultExpanded | string[] | undefined | — | The value of the expanded tree when initially rendered. Use when you do not need to control the state of the expanded tree |
getKey* | (val: TItem) => string | — | This function is passed the index of each item and should return a unique key for that item |
getChildren | ((val: TItem) => TItem[] | undefined) | undefined | — | This function is passed the index of each item and should return a list of children for that item |
selectionBehavior | "toggle" | "replace" | undefined | — | How multiple selection should behave in the collection. |
multiple | boolean | Multiple | undefined | — | Whether multiple options can be selected or not. |
dir | Direction | undefined | — | The reading direction of the listbox when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
disabled | boolean | undefined | — | When `true`, prevents the user from interacting with tree |
propagateSelect | boolean | undefined | — | When `true`, selecting parent will select the descendants. Requires `multiple` to be `true`. |
bubbleSelect | boolean | undefined | — | When `true`, selecting children will update the parent state. Requires `multiple` to be `true`. |
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
* 代表必填
Events
| 名稱 | Payload | 說明 |
|---|---|---|
update:modelValue | Multiple extends true ? TValue[] : TValue | — |
update:expanded | string[] | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | { flattenItems: FlattenedItem<TItem>[]; modelValue: Multiple extends true ? TValue[] : TValue; expanded: string[]; } | 預設 slot,提供樹狀資料展開後之 flattened items、當前 modelValue 與展開狀態 |
admin-tree-item
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
class | ClassValue | — | 根元素之自訂 class |
value* | TItem | — | Value given to this item |
level* | number | — | Level of depth |
disabled | boolean | undefined | — | When `true`, prevents the user from interacting with the item. |
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
hasChildren | boolean | undefined | — | 設為 `true` 時顯示展開/收合 caret icon |
* 代表必填
Events
| 名稱 | Payload | 說明 |
|---|---|---|
select | SelectEvent<TItem> | — |
toggle | ToggleEvent<TItem> | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | { isExpanded: boolean; isSelected: boolean; isIndeterminate: boolean | undefined; } | 預設 slot,提供節點互動狀態 |
prefix | { isExpanded: boolean; isSelected: boolean; isIndeterminate: boolean | undefined; hasChildren: boolean | undefined; handleToggle: () => void; handleSelect: () => void; } | 節點前綴 slot(預設渲染展開 caret),可覆蓋自訂 |