---
title: "Tree"
description: "A tree component built on Nuxt UI Tree, adding search, lazy loading, toolbar, checkboxes, and parent/child strategy."
canonical_url: "https://nuxt.mhaibaraai.cn/en/docs/components/tree"
---
# Tree

> A tree component built on Nuxt UI Tree, adding search, lazy loading, toolbar, checkboxes, and parent/child strategy.

## Introduction

`MTree` is a thin wrapper over Nuxt UI `Tree`, fully passing through all its props, events, and slots while adding several enhancements: search filtering with highlight, async lazy loading, a toolbar (expand/collapse toggle, tri-state select all), checkbox multi-select with parent/child strategy (cascade / isolated), key binding (`v-model:selectedKeys`), an imperative API, and selection categorization. Tree data normalization, filtering, and traversal reuse the `Tree` utility methods from `@movk/core`.

> [!NOTE]
> See: https://ui.nuxt.com/docs/components/tree
> 
> Built on Nuxt UI's Tree component — all native props and slots are fully passed through

## Usage

Pass `items` to render a hierarchical structure. Node `defaultExpanded` controls the initial expansion, and `v-model` binds the selected node:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"},{"label":"useUser.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
const value = ref({"label":"app.vue"})
</script>

<template>
  <MTree :items="items" />
</template>
```

### `defaultExpanded` Default Expansion

`defaultExpanded` derives the initially expanded parent nodes from a strategy, falling back to the node's own `defaultExpanded` flag. Pass `true` to expand all parents, a `number` to expand only parents with depth less than that value, or a function for custom logic per node and depth:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","children":[{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"},{"label":"useUser.ts","icon":"i-vscode-icons-file-type-typescript"}]},{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"}]},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}])
</script>

<template>
  <MTree :items="items" default-expanded />
</template>
```

### `searchable` Search Filtering

`searchable` renders a search input at the top, prunes the tree by keyword while preserving ancestor chains for matching nodes. `highlight` is enabled by default, highlighting matched text and auto-expanding on match. `filter` allows a custom match predicate. `search` supports `v-model:search` two-way binding of the keyword:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"},{"label":"useUser.ts","icon":"i-vscode-icons-file-type-typescript"}]},{"label":"components","icon":"i-lucide-folder","children":[{"label":"Card.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"Button.vue","icon":"i-vscode-icons-file-type-vue"}]}])
</script>

<template>
  <MTree :items="items" searchable />
</template>
```

### `checkable` Checkbox Cascade

`checkable` renders a checkbox before each node, internally enables `multiple` with parent/child cascade and indeterminate state bubbling. `v-model` collects the selected node array. Checkboxes coexist with node `icon` and parent folder icons:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"},{"label":"useUser.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
const value = ref([])
</script>

<template>
  <MTree :items="items" checkable />
</template>
```

> [!NOTE]
> 
> checkable
> 
>  is syntactic sugar for 
> 
> multiple
> 
>  + 
> 
> strategy
> 
>  (default 
> 
> cascade
> 
> ). Use 
> 
> multiple
> 
>  instead when you need multi-select without rendering checkboxes.

### `multiple` Multiple Selection

`multiple` enables multi-select without rendering checkboxes. Clicking a node accumulates the selection. `v-model` collects the selected node array:

```vue
<script setup lang="ts">
const items = ref([{"label":"Tech Center","defaultExpanded":true,"children":[{"label":"Frontend","children":[{"label":"Component Library"},{"label":"Visualization"}]},{"label":"Backend"}]},{"label":"Product Center","children":[{"label":"UX Design"}]}])
const value = ref([])
</script>

<template>
  <MTree :items="items" multiple />
</template>
```

### `strategy` Parent/Child Strategy

`strategy` controls the parent/child check relationship in multi-select / `checkable` mode. `cascade` (default) cascades parent/child and re-fills the parent when all children are selected. `isolated` keeps parent and child independent — indeterminate state does not bubble:

```vue
<script setup lang="ts">
const items = ref([{"label":"Tech Center","defaultExpanded":true,"children":[{"label":"Frontend","children":[{"label":"Component Library"},{"label":"Visualization"}]},{"label":"Backend","children":[{"label":"Gateway"},{"label":"Storage"}]}]}])
const value = ref([])
</script>

<template>
  <MTree :items="items" checkable strategy="cascade" />
</template>
```

### `selectedKeys` Key Binding

`selectedKeys` two-way binds the selection using an array of node keys — useful for re-populating from the backend or syncing with routes. `v-model:selectedKeys` and `v-model` are interoperable. Keys are derived from `getKey` / `labelKey`:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]}])
</script>

<template>
  <MTree v-model:selected-keys="selectedKeys" :items="items" checkable />
</template>
```

### `toolbar` Toolbar

`toolbar` renders a top toolbar with expand/collapse toggle buttons. When `searchable` is set, it embeds a clearable search input. When `checkable` is set, it adds a tri-state select-all checkbox and selection count:

```vue
<script setup lang="ts">
const items = ref([{"label":"Tech Center","children":[{"label":"Frontend","children":[{"label":"Component Library"},{"label":"Visualization"}]},{"label":"Backend","children":[{"label":"Gateway"},{"label":"Storage"}]}]},{"label":"Product Center","children":[{"label":"UX Design"},{"label":"User Research"}]}])
const value = ref([])
</script>

<template>
  <MTree :items="items" toolbar searchable checkable />
</template>
```

> [!NOTE]
> 
> The toolbar's select-all count is based on 
> 
> leaves
> 
> : in cascade mode, selecting a parent brings in child keys. Counting by leaves avoids double counting.

### `lazy` Async Lazy Loading

`lazy` works with `loadChildren` — expanding an unloaded parent node fetches child nodes and displays a loading state. The `isLeaf` flag on a node marks it as a leaf, preventing expansion placeholder rendering:

```vue [ComponentsTreeLazyExample.vue]
<script setup lang="ts">
import type { TreeItem } from '@movk/nuxt'

const items: TreeItem[] = [
  { label: '区域 A' },
  { label: '区域 B' },
  { label: '直辖节点', isLeaf: true }
]

let seq = 0
function loadChildren(node: TreeItem): Promise<TreeItem[]> {
  return new Promise(resolve => setTimeout(() => {
    seq += 1
    resolve([
      { label: `${node.label} / 子节点 ${seq}-1` },
      { label: `${node.label} / 子节点 ${seq}-2`, isLeaf: true }
    ])
  }, 800))
}
</script>

<template>
  <MTree :items="items" lazy :load-children="loadChildren" />
</template>
```

### `childrenKey` Field Mapping

`childrenKey` normalizes the backend's child node field to `children`. `labelKey` specifies the display field, eliminating the need to pre-transform data structures:

```vue
<script setup lang="ts">
const items = ref([{"name":"Tech Center","nodes":[{"name":"Frontend","nodes":[{"name":"Component Library"},{"name":"Visualization"}]},{"name":"Backend"}]},{"name":"Product Center","nodes":[{"name":"UX Design"}]}])
</script>

<template>
  <MTree :items="items" children-key="nodes" label-key="name" />
</template>
```

### `labelKey` Dot-Path Value Extraction

`labelKey` specifies the node display field, supporting dot-path deep extraction of nested fields like `meta.title`. Key derivation, search, and highlight all use the same path:

```vue
<script setup lang="ts">
const items = ref([{"meta":{"title":"Tech Center"},"children":[{"meta":{"title":"Frontend"},"children":[{"meta":{"title":"Component Library"}},{"meta":{"title":"Visualization"}}]},{"meta":{"title":"Backend"}}]},{"meta":{"title":"Product Center"},"children":[{"meta":{"title":"UX Design"}}]}])
</script>

<template>
  <MTree :items="items" label-key="meta.title" searchable />
</template>
```

> [!NOTE]
> 
> The dot-path must align with UTree's internal value extraction. Only dot notation (
> 
> a.b.c
> 
> ) is supported — bracket notation (
> 
> a[0].b
> 
> ) is not.

### `virtualize` Virtual Scrolling

`virtualize` passes through Nuxt UI Tree's virtualization capability, rendering only visible nodes — suitable for large data sets:

```vue [ComponentsTreeVirtualizeExample.vue]
<script setup lang="ts">
import type { TreeItem } from '@movk/nuxt'

const items: TreeItem[] = Array.from({ length: 60 }, (_, group) => ({
  label: `分组 ${group + 1}`,
  defaultExpanded: group === 0,
  children: Array.from({ length: 30 }, (_, leaf) => ({ label: `节点 ${group + 1}-${leaf + 1}` }))
}))
</script>

<template>
  <MTree :items="items" :virtualize="true" class="max-h-72 w-md" />
</template>
```

### `color` Primary Color

`color` passes through Nuxt UI Tree's primary color, applying to selected node text color and keyboard focus ring. The example pre-selects a node for visual reference:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
const value = ref({"label":"app.vue"})
</script>

<template>
  <MTree :items="items" color="error" />
</template>
```

> [!NOTE]
> 
> UTree's 
> 
> color
> 
>  only applies to selected node text and focus ring. No visible change occurs when no node is selected. Single-color icons (e.g., lucide) inherit the text color; multi-color icons (e.g., vscode-icons) maintain their own coloring.

### `trailingIcon` Trailing Icon

`trailingIcon` replaces the expand indicator icon at the end of parent nodes (default `i-lucide-chevron-down`). `item.trailingIcon` on node data takes higher priority:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","trailingIcon":"i-lucide-arrow-down","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
</script>

<template>
  <MTree :items="items" trailing-icon="i-lucide-chevron-right" />
</template>
```

### `expandedIcon` Expand Icon

`expandedIcon` / `collapsedIcon` customize the leading icon for parent nodes when expanded / collapsed (default `i-lucide-folder-open` / `i-lucide-folder`):

```vue
<script setup lang="ts">
const items = ref([{"label":"app","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
</script>

<template>
  <MTree :items="items" expanded-icon="i-lucide-book-open" collapsed-icon="i-lucide-book" />
</template>
```

> [!NOTE]
> 
> item.icon
> 
>  on a node takes higher priority than 
> 
> expandedIcon
> 
>  / 
> 
> collapsedIcon
> 
> . Therefore, folders that need to switch icons based on expanded state should not set 
> 
> item.icon
> 
> .

### `disabled` Disabled

`disabled` disables the entire tree, blocking click events on nodes, toolbar controls, and checkboxes for expand, collapse, and select operations. Per-node `item.disabled` disables that node and its entire subtree — freezing expansion state and disabling checkboxes within the subtree:

```vue
<script setup lang="ts">
const items = ref([{"label":"app","icon":"i-lucide-folder","defaultExpanded":true,"children":[{"label":"app.vue","icon":"i-vscode-icons-file-type-vue"},{"label":"nuxt.config.ts","icon":"i-vscode-icons-file-type-nuxt"}]},{"label":"composables","icon":"i-lucide-folder","children":[{"label":"useAuth.ts","icon":"i-vscode-icons-file-type-typescript"}]}])
const value = ref([{"label":"useAuth.ts"}])
</script>

<template>
  <MTree :items="items" checkable toolbar disabled />
</template>
```

> [!NOTE]
> 
> Imperative API methods (
> 
> expandToDepth
> 
> , 
> 
> selectAll
> 
> , etc.) are explicit calls and are not affected by 
> 
> disabled
> 
> . 
> 
> disabled
> 
>  only intercepts user clicks and toolbar interactions.

## Examples

### Custom Node

Customize node content via passed-through slots like `item-trailing`. Uncovered slots are still rendered by Nuxt UI Tree's defaults:

```vue [ComponentsTreeSlotExample.vue]
<script setup lang="ts">
import type { TreeItem } from '@movk/nuxt'

const items: TreeItem[] = [
  {
    label: 'app',
    icon: 'i-lucide-folder',
    defaultExpanded: true,
    children: [
      { label: 'app.vue', icon: 'i-vscode-icons-file-type-vue' },
      { label: 'nuxt.config.ts', icon: 'i-vscode-icons-file-type-nuxt' }
    ]
  }
]
</script>

<template>
  <MTree :items="items">
    <template #item-trailing="{ item }">
      <UBadge v-if="!item.children" label="file" color="neutral" variant="subtle" size="sm" />
    </template>
  </MTree>
</template>
```

### Custom Toolbar

`toolbar-leading` / `toolbar-trailing` append content to the start/end of the default toolbar. Use the `#toolbar` slot for full control — its scope exposes methods and state like `toggleExpand`, `selectAll`, `clear`, and `selectionSummary`:

```vue [ComponentsTreeCustomToolbarExample.vue]
<script setup lang="ts">
import type { TreeItem } from '@movk/nuxt'

const items: TreeItem[] = [
  {
    label: '技术中心',
    children: [
      { label: '前端组', children: [{ label: '组件库' }, { label: '可视化' }] },
      { label: '后端组', children: [{ label: '网关' }, { label: '存储' }] }
    ]
  },
  { label: '产品中心', children: [{ label: '交互设计' }, { label: '用户研究' }] }
]

const checked = ref<TreeItem[]>([])
</script>

<template>
  <MTree v-model="checked" :items="items" toolbar searchable checkable>
    <template #toolbar-leading>
      <UBadge label="部门" color="neutral" variant="subtle" size="sm" />
    </template>
    <template #toolbar-trailing>
      <UBadge :label="`${checked.length} 项`" color="primary" variant="subtle" size="sm" />
    </template>
  </MTree>
</template>
```

### Imperative Control

Obtain the component instance via `useTemplateRef` and call methods like `expandToDepth`, `collapseAll`, `selectAll`, and `clearSelection` to control the tree:

```vue [ComponentsTreeImperativeExample.vue]
<script setup lang="ts">
import type { TreeExposed, TreeItem } from '@movk/nuxt'

const items: TreeItem[] = [
  {
    label: '技术中心',
    children: [
      { label: '前端组', children: [{ label: '组件库' }, { label: '可视化' }] },
      { label: '后端组', children: [{ label: '网关' }, { label: '存储' }] }
    ]
  },
  { label: '产品中心', children: [{ label: '交互设计' }, { label: '用户研究' }] }
]

const checked = ref<TreeItem[]>([])
const tree = useTemplateRef<TreeExposed>('tree')
</script>

<template>
  <div class="space-y-3">
    <div class="flex flex-wrap gap-2">
      <UButton size="xs" label="展开到第 2 层" @click="tree?.expandToDepth(2)" />
      <UButton size="xs" label="收起全部" color="neutral" variant="subtle" @click="tree?.collapseAll()" />
      <UButton size="xs" label="全选" @click="tree?.selectAll()" />
      <UButton size="xs" label="清空" color="neutral" variant="subtle" @click="tree?.clearSelection()" />
    </div>
    <MTree ref="tree" v-model="checked" :items="items" checkable />
  </div>
</template>
```

### Selection Categorization

The instance's reactive `treeSelection` returns selection categories: `leaves` (selected leaves), `parents` (fully selected parents), `halfSelected` (indeterminate parents), and `strictlyChecked` (excludes children selected via parent cascade):

```vue [ComponentsTreeSelectionExample.vue]
<script setup lang="ts">
import type { TreeExposed, TreeItem } from '@movk/nuxt'

const items: TreeItem[] = [
  {
    label: '技术中心',
    defaultExpanded: true,
    children: [
      { label: '前端组', children: [{ label: '组件库' }, { label: '可视化' }] },
      { label: '后端组', children: [{ label: '网关' }, { label: '存储' }] }
    ]
  }
]

const checked = ref<TreeItem[]>([])
const tree = useTemplateRef<TreeExposed>('tree')

const labels = (nodes?: TreeItem[]) => (nodes ?? []).map(node => node.label).join('、') || '无'
</script>

<template>
  <div class="space-y-3">
    <MTree ref="tree" v-model="checked" :items="items" checkable />
    <dl class="text-sm text-muted space-y-1">
      <div>叶子（leaves）：{{ labels(tree?.treeSelection.leaves) }}</div>
      <div>满选父级（parents）：{{ labels(tree?.treeSelection.parents) }}</div>
      <div>半选父级（halfSelected）：{{ labels(tree?.treeSelection.halfSelected) }}</div>
    </dl>
  </div>
</template>
```

## API

### Props

```ts
/**
 * Props for the MTree component
 */
interface MTreeProps {
  /**
   * 树数据源，按 childrenKey 解析层级
   */
  items?: T | undefined;
  /**
   * 取子节点数组的字段名，归一化为 UTree 的 children
   * @default 'children'
   */
  childrenKey?: string | undefined;
  /**
   * 展示字段名
   * @default 'label'
   */
  labelKey?: keyof Extract<NestedItem<T>, object> & string | DotPathKeys<Extract<NestedItem<T>, object>> | undefined;
  /**
   * 自定义节点 key，缺省取 labelKey 字段值
   */
  getKey?: (val: T[number]): string | undefined;
  /**
   * 初始展开策略，缺省回退节点上的 defaultExpanded 标记
   * - true 展开全部父级
   * - number 展开 depth 小于该值的父级
   * - 函数 按节点与深度自定义
   */
  defaultExpanded?: number | false | true | (node: T[number], depth: number): boolean | undefined;
  /**
   * 选中节点 key 列表，可用 v-model:selectedKeys 双向绑定
   */
  selectedKeys?: string[] | undefined;
  /**
   * 开启多选
   */
  multiple?: M | undefined;
  /**
   * 多选 / checkable 下的父子勾选策略
   * - 'cascade' 父子级联（propagateSelect + bubbleSelect）
   * - 'isolated' 父子互不关联
   * @default 'cascade'
   */
  strategy?: "cascade" | "isolated" | undefined;
  /**
   * 选中父节点时级联选中子节点。cascade 策略下默认开启，显式 true 可在 isolated 下强制开启；关闭级联请用 strategy='isolated'
   */
  propagateSelect?: boolean | undefined;
  /**
   * 子节点全部选中时回填父节点。cascade 策略下默认开启，显式 true 可在 isolated 下强制开启；关闭级联请用 strategy='isolated'
   */
  bubbleSelect?: boolean | undefined;
  /**
   * 尺寸
   * @default 'md'
   */
  size?: "md" | "xs" | "sm" | "lg" | "xl" | undefined;
  /**
   * 主色
   * @default 'primary'
   */
  color?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "important" | "neutral" | undefined;
  /**
   * 父节点展开时的图标
   * @default 取 app.config 的 ui.icons.folderOpen
   */
  expandedIcon?: any;
  /**
   * 父节点折叠时的图标
   * @default 取 app.config 的 ui.icons.folder
   */
  collapsedIcon?: any;
  /**
   * 禁用整棵树，阻断点击、工具栏与复选框的展开、折叠、选中
   */
  disabled?: boolean | undefined;
  /**
   * 开启顶部搜索过滤
   */
  searchable?: boolean | undefined;
  /**
   * 自定义匹配谓词，缺省按 labelKey 文本不区分大小写包含匹配
   */
  filter?: (node: T[number], term: string): boolean | undefined;
  /**
   * 高亮命中文本，仅在 searchable 时生效
   * @default true
   */
  highlight?: boolean | undefined;
  /**
   * 开启异步懒加载子节点
   */
  lazy?: boolean | undefined;
  /**
   * 懒加载回调，展开未加载的父节点时调用
   */
  loadChildren?: (node: T[number]): Promise<T[number][]> | undefined;
  /**
   * 开启顶部工具栏（展开/折叠，checkable 时附带全选/清空）
   */
  toolbar?: boolean | undefined;
  /**
   * 渲染复选框并启用多选（multiple + strategy，默认 cascade）
   */
  checkable?: M | undefined;
  ui?: Record<string, C> & { root?: SlotClass; item?: SlotClass; listWithChildren?: SlotClass; itemWithChildren?: SlotClass; link?: SlotClass; linkLeadingIcon?: SlotClass; linkLabel?: SlotClass; linkTrailing?: SlotClass; linkTrailingIcon?: SlotClass; container?: SlotClass; toolbar?: SlotClass; toolbarButton?: SlotClass; search?: SlotClass; checkbox?: SlotClass; highlight?: SlotClass; loading?: SlotClass; loadingIcon?: SlotClass; empty?: SlotClass; } | undefined;
  /**
   * The element or component this component should render as.
   * @default 'ul'
   */
  as?: any;
  /**
   * The icon displayed on the right side of a parent node.
   * @default appConfig.ui.icons.chevronDown
   */
  trailingIcon?: any;
  /**
   * The controlled value of the Tree. Can be bind as `v-model`.
   */
  modelValue?: M extends true ? T[number][] : T[number] | undefined;
  /**
   * The value of the Tree when initially rendered. Use when you do not need to control the state of the Tree.
   */
  defaultValue?: M extends true ? T[number][] : T[number] | undefined;
  /**
   * Use nested DOM structure (children inside parents) vs flattened structure (all items at same level).
   * When `virtualize` is enabled, this is automatically set to `false`.
   * @default true
   */
  nested?: boolean | undefined;
  /**
   * Enable virtualization for large lists.
   * Note: when enabled, the tree structure is flattened like if `nested` was set to `false`.
   * @default false
   */
  virtualize?: boolean | { overscan?: number | undefined; estimateSize?: number | ((index: number) => number) | undefined; } | undefined;
  onSelect?: (e: SelectEvent<T[number]>, item: T[number]): void | undefined;
  onToggle?: (e: ToggleEvent<T[number]>, item: T[number]): void | undefined;
  /**
   * The controlled value of the expanded item. Can be binded with `v-model`.
   * @default []
   */
  expanded?: string[] | undefined;
  /**
   * How multiple selection should behave in the collection.
   */
  selectionBehavior?: "replace" | "toggle" | undefined;
  /**
   * @default ''
   */
  search?: string | undefined;
}
```

### Emits

```ts
/**
 * Emitted events for the MTree component
 */
interface MTreeEmits {
  update:modelValue: (payload: [val: M extends true ? T[number][] : T[number]]) => void;
  update:expanded: (payload: [val: string[]]) => void;
  update:search: (payload: [value: string]) => void;
  change: (payload: [payload: { value: (M extends true ? T[number][] : T[number]) | undefined; keys: string[]; selection: TreeSelectionResult<T[number]>; }]) => void;
  update:modelValue: (payload: [value: (M extends true ? T[number][] : T[number]) | undefined]) => void;
  update:selectedKeys: (payload: [value: string[] | undefined]) => void;
}
```

> [!TIP]
> 
> In addition to passing through Nuxt UI Tree's `update:modelValue` and `update:expanded`, `MTree` additionally provides:
> 
> - `update:search`: Fires when the search keyword changes, supports `v-model:search`.
> - `update:selectedKeys`: Fires when the selected key list changes, supports `v-model:selectedKeys`.
> - `change`: Fires when the selection changes. Payload is `{ value, keys, selection }`. `keys` is derived from `getKey`/`labelKey`. `selection` is the selection categorization result.

### Slots

```ts
/**
 * Slots for the MTree component
 */
interface MTreeSlots {
  item-wrapper(): any;
  item(): any;
  item-leading(): any;
  item-label(): any;
  item-trailing(): any;
  toolbar(): any;
  /**
   * 默认工具栏起始处追加内容
   */
  toolbar-leading(): any;
  /**
   * 默认工具栏末尾追加内容
   */
  toolbar-trailing(): any;
  empty(): any;
  loading(): any;
}
```

### Expose

You can access the typed component instance via [`useTemplateRef`](https://vuejs.org/api/composition-api-helpers.html#usetemplateref).

| Name | Type |
| --- | --- |
| `expandAll()` | `void` <br> Expand all expandable nodes |
| `collapseAll()` | `void` <br> Collapse all nodes |
| `expandToDepth(depth)` | `void` <br> Expand to the specified depth. `depth=0` collapses all |
| `selectAll()` | `void` <br> Select all selectable nodes |
| `clearSelection()` | `void` <br> Clear all selections |
| `treeSelection` | `TreeSelectionResult` <br> Current selection categorization (`selected` / `leaves` / `parents` / `halfSelected` / `strictlyChecked`) |

## Theme

<component-theme>



</component-theme>

## Changelog

See commit history for [src/runtime/components/Tree.vue](https://github.com/mhaibaraai/movk-nuxt/commits/main/src/runtime/components/Tree.vue).


## Sitemap

See the full [sitemap](https://nuxt.mhaibaraai.cn/sitemap.md) for all pages.
