开发预览 更新于 2026-05-10

TreeSelect 树形选择

树形数据下拉选择器,支持展开/折叠、多选级联、indeterminate、搜索、清空、禁用节点。

基础用法

CfTreeSelect 面向部门、权限、资源目录、地区等层级数据。每个分支节点旁边有展开/折叠按钮(chevron),搜索时会自动展开命中节点的所有祖先。

背景 视口

已选:edge-workers

src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfTreeSelect, type TreeSelectNode } from '@chufix-design/vue';

const value = ref('edge-workers');
const options: TreeSelectNode[] = [
  {
    value: 'platform',
    label: '平台能力',
    children: [
      { value: 'edge-workers', label: 'Workers' },
      { value: 'storage-d1', label: 'D1 数据库' },
      { value: 'storage-r2', label: 'R2 存储' },
    ],
  },
  {
    value: 'product',
    label: '产品体验',
    children: [
      { value: 'docs', label: '文档站' },
      { value: 'dashboard', label: '控制台' },
      { value: 'billing', label: '计费中心', disabled: true },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect v-model="value" :options="options" searchable clearable />
    <p class="demo-hint">已选:<code>{{ value ?? 'undefined' }}</code></p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfTreeSelect } from '@chufix-design/vue';

const value = ref('edge-workers');
const options= [
  {
    value: 'platform',
    label: '平台能力',
    children: [
      { value: 'edge-workers', label: 'Workers' },
      { value: 'storage-d1', label: 'D1 数据库' },
      { value: 'storage-r2', label: 'R2 存储' },
    ],
  },
  {
    value: 'product',
    label: '产品体验',
    children: [
      { value: 'docs', label: '文档站' },
      { value: 'dashboard', label: '控制台' },
      { value: 'billing', label: '计费中心', disabled: true },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect v-model="value" :options="options" searchable clearable />
    <p class="demo-hint">已选:<code>{{ value ?? 'undefined' }}</code></p>
  </div>
</template>
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState('edge-workers');
  const options: TreeSelectNode[] = [
    {
      value: 'platform',
      label: '平台能力',
      children: [
        { value: 'edge-workers', label: 'Workers' },
        { value: 'storage-d1', label: 'D1 数据库' },
        { value: 'storage-r2', label: 'R2 存储' },
      ],
    },
    {
      value: 'product',
      label: '产品体验',
      children: [
        { value: 'docs', label: '文档站' },
        { value: 'dashboard', label: '控制台' },
        { value: 'billing', label: '计费中心', disabled: true },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={value} onChange={setValue} options={options} searchable clearable />
          <p className="demo-hint">已选:<code>{value ?? 'undefined'}</code></p>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState('edge-workers');
  const options= [
    {
      value: 'platform',
      label: '平台能力',
      children: [
        { value: 'edge-workers', label: 'Workers' },
        { value: 'storage-d1', label: 'D1 数据库' },
        { value: 'storage-r2', label: 'R2 存储' },
      ],
    },
    {
      value: 'product',
      label: '产品体验',
      children: [
        { value: 'docs', label: '文档站' },
        { value: 'dashboard', label: '控制台' },
        { value: 'billing', label: '计费中心', disabled: true },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={value} onChange={setValue} options={options} searchable clearable />
          <p className="demo-hint">已选:<code>{value ?? 'undefined'}</code></p>
        </div>
    </>
  );
}

多选与级联

multiple 开启多选;默认开启 cascade:点击父节点会级联选中所有可用子节点;当部分子节点被选中时,父节点显示 indeterminate 状态。disabled 子节点不会被级联影响。

背景 视口

已选 2 项 — 点父节点会级联选中所有可用子节点。

src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfTreeSelect, type TreeSelectNode } from '@chufix-design/vue';

const value = ref<string[]>(['edge-workers', 'storage-r2']);
const options: TreeSelectNode[] = [
  {
    value: 'platform',
    label: '平台能力',
    children: [
      { value: 'edge-workers', label: 'Workers' },
      { value: 'storage-d1', label: 'D1 数据库' },
      { value: 'storage-r2', label: 'R2 存储' },
      { value: 'storage-kv', label: 'KV 存储' },
    ],
  },
  {
    value: 'product',
    label: '产品体验',
    children: [
      { value: 'docs', label: '文档站' },
      { value: 'dashboard', label: '控制台' },
      { value: 'billing', label: '计费中心', disabled: true },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect
      v-model="value"
      :options="options"
      multiple
      searchable
      clearable
      :default-expanded-keys="['platform']"
    />
    <p class="demo-hint">
      已选 <code>{{ value.length }}</code> 项 — 点父节点会级联选中所有可用子节点。
    </p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfTreeSelect } from '@chufix-design/vue';

const value = ref<string[]>(['edge-workers', 'storage-r2']);
const options= [
  {
    value: 'platform',
    label: '平台能力',
    children: [
      { value: 'edge-workers', label: 'Workers' },
      { value: 'storage-d1', label: 'D1 数据库' },
      { value: 'storage-r2', label: 'R2 存储' },
      { value: 'storage-kv', label: 'KV 存储' },
    ],
  },
  {
    value: 'product',
    label: '产品体验',
    children: [
      { value: 'docs', label: '文档站' },
      { value: 'dashboard', label: '控制台' },
      { value: 'billing', label: '计费中心', disabled: true },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect
      v-model="value"
      :options="options"
      multiple
      searchable
      clearable
      :default-expanded-keys="['platform']"
    />
    <p class="demo-hint">
      已选 <code>{{ value.length }}</code> 项 — 点父节点会级联选中所有可用子节点。
    </p>
  </div>
</template>
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState<string[]>(['edge-workers', 'storage-r2']);
  const options: TreeSelectNode[] = [
    {
      value: 'platform',
      label: '平台能力',
      children: [
        { value: 'edge-workers', label: 'Workers' },
        { value: 'storage-d1', label: 'D1 数据库' },
        { value: 'storage-r2', label: 'R2 存储' },
        { value: 'storage-kv', label: 'KV 存储' },
      ],
    },
    {
      value: 'product',
      label: '产品体验',
      children: [
        { value: 'docs', label: '文档站' },
        { value: 'dashboard', label: '控制台' },
        { value: 'billing', label: '计费中心', disabled: true },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={value} onChange={setValue} options={options} multiple searchable clearable defaultExpandedKeys={['platform']} />
          <p className="demo-hint">
            已选 <code>{value.length}</code> 项 — 点父节点会级联选中所有可用子节点。
          </p>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState<string[]>(['edge-workers', 'storage-r2']);
  const options= [
    {
      value: 'platform',
      label: '平台能力',
      children: [
        { value: 'edge-workers', label: 'Workers' },
        { value: 'storage-d1', label: 'D1 数据库' },
        { value: 'storage-r2', label: 'R2 存储' },
        { value: 'storage-kv', label: 'KV 存储' },
      ],
    },
    {
      value: 'product',
      label: '产品体验',
      children: [
        { value: 'docs', label: '文档站' },
        { value: 'dashboard', label: '控制台' },
        { value: 'billing', label: '计费中心', disabled: true },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={value} onChange={setValue} options={options} multiple searchable clearable defaultExpandedKeys={['platform']} />
          <p className="demo-hint">
            已选 <code>{value.length}</code> 项 — 点父节点会级联选中所有可用子节点。
          </p>
        </div>
    </>
  );
}

默认展开节点

defaultExpandedKeys 接受节点 value 数组,或字符串 'all' 一次性展开整棵树。未列出的分支节点会保持折叠。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfTreeSelect, type TreeSelectNode } from '@chufix-design/vue';

const a = ref<string | undefined>(undefined);
const b = ref<string | undefined>(undefined);

const options: TreeSelectNode[] = [
  {
    value: 'cn',
    label: '中国',
    children: [
      {
        value: 'cn-east',
        label: '华东',
        children: [
          { value: 'sh', label: '上海' },
          { value: 'hz', label: '杭州' },
        ],
      },
      {
        value: 'cn-south',
        label: '华南',
        children: [
          { value: 'gz', label: '广州' },
          { value: 'sz', label: '深圳' },
        ],
      },
    ],
  },
  {
    value: 'us',
    label: '美国',
    children: [
      { value: 'us-west', label: '西海岸' },
      { value: 'us-east', label: '东海岸' },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect
      v-model="a"
      :options="options"
      placeholder="默认全部展开"
      default-expanded-keys="all"
      searchable
    />
    <CfTreeSelect
      v-model="b"
      :options="options"
      placeholder="只展开根 + 华东"
      :default-expanded-keys="['cn', 'cn-east']"
    />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfTreeSelect } from '@chufix-design/vue';

const a = ref<string | undefined>(undefined);
const b = ref<string | undefined>(undefined);

const options= [
  {
    value: 'cn',
    label: '中国',
    children: [
      {
        value: 'cn-east',
        label: '华东',
        children: [
          { value: 'sh', label: '上海' },
          { value: 'hz', label: '杭州' },
        ],
      },
      {
        value: 'cn-south',
        label: '华南',
        children: [
          { value: 'gz', label: '广州' },
          { value: 'sz', label: '深圳' },
        ],
      },
    ],
  },
  {
    value: 'us',
    label: '美国',
    children: [
      { value: 'us-west', label: '西海岸' },
      { value: 'us-east', label: '东海岸' },
    ],
  },
];
</script>
<template>
  <div class="demo-stack">
    <CfTreeSelect
      v-model="a"
      :options="options"
      placeholder="默认全部展开"
      default-expanded-keys="all"
      searchable
    />
    <CfTreeSelect
      v-model="b"
      :options="options"
      placeholder="只展开根 + 华东"
      :default-expanded-keys="['cn', 'cn-east']"
    />
  </div>
</template>
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState<string | undefined>(undefined);
  const [b, setB] = useState<string | undefined>(undefined);

  const options: TreeSelectNode[] = [
    {
      value: 'cn',
      label: '中国',
      children: [
        {
          value: 'cn-east',
          label: '华东',
          children: [
            { value: 'sh', label: '上海' },
            { value: 'hz', label: '杭州' },
          ],
        },
        {
          value: 'cn-south',
          label: '华南',
          children: [
            { value: 'gz', label: '广州' },
            { value: 'sz', label: '深圳' },
          ],
        },
      ],
    },
    {
      value: 'us',
      label: '美国',
      children: [
        { value: 'us-west', label: '西海岸' },
        { value: 'us-east', label: '东海岸' },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={a} onChange={setA} options={options} placeholder="默认全部展开" default-expanded-keys="all" searchable />
          <CfTreeSelect value={b} onChange={setB} options={options} placeholder="只展开根 + 华东" defaultExpandedKeys={['cn', 'cn-east']} />
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState<string | undefined>(undefined);
  const [b, setB] = useState<string | undefined>(undefined);

  const options= [
    {
      value: 'cn',
      label: '中国',
      children: [
        {
          value: 'cn-east',
          label: '华东',
          children: [
            { value: 'sh', label: '上海' },
            { value: 'hz', label: '杭州' },
          ],
        },
        {
          value: 'cn-south',
          label: '华南',
          children: [
            { value: 'gz', label: '广州' },
            { value: 'sz', label: '深圳' },
          ],
        },
      ],
    },
    {
      value: 'us',
      label: '美国',
      children: [
        { value: 'us-west', label: '西海岸' },
        { value: 'us-east', label: '东海岸' },
      ],
    },
  ];
  return (
    <>
      <div className="demo-stack">
          <CfTreeSelect value={a} onChange={setA} options={options} placeholder="默认全部展开" default-expanded-keys="all" searchable />
          <CfTreeSelect value={b} onChange={setB} options={options} placeholder="只展开根 + 华东" defaultExpandedKeys={['cn', 'cn-east']} />
        </div>
    </>
  );
}

关闭引导线

层级关系默认通过竖向引导线展示。在节点文本较长或想要更紧凑外观时,showLines={false} 只保留缩进。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfTreeSelect, type TreeSelectNode } from '@chufix-design/vue';

const value = ref<string | undefined>(undefined);
const options: TreeSelectNode[] = [
  {
    value: 'design',
    label: '设计系统',
    children: [
      { value: 'tokens', label: 'Tokens' },
      { value: 'components', label: 'Components' },
    ],
  },
  {
    value: 'engineering',
    label: '工程',
    children: [
      { value: 'frontend', label: '前端' },
      { value: 'backend', label: '后端' },
    ],
  },
];
</script>
<template>
  <CfTreeSelect
    v-model="value"
    :options="options"
    placeholder="紧凑:关闭引导线"
    :show-lines="false"
    default-expanded-keys="all"
  />
</template>
<script setup>
import { ref } from 'vue';
import { CfTreeSelect } from '@chufix-design/vue';

const value = ref<string | undefined>(undefined);
const options= [
  {
    value: 'design',
    label: '设计系统',
    children: [
      { value: 'tokens', label: 'Tokens' },
      { value: 'components', label: 'Components' },
    ],
  },
  {
    value: 'engineering',
    label: '工程',
    children: [
      { value: 'frontend', label: '前端' },
      { value: 'backend', label: '后端' },
    ],
  },
];
</script>
<template>
  <CfTreeSelect
    v-model="value"
    :options="options"
    placeholder="紧凑:关闭引导线"
    :show-lines="false"
    default-expanded-keys="all"
  />
</template>
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState<string | undefined>(undefined);
  const options: TreeSelectNode[] = [
    {
      value: 'design',
      label: '设计系统',
      children: [
        { value: 'tokens', label: 'Tokens' },
        { value: 'components', label: 'Components' },
      ],
    },
    {
      value: 'engineering',
      label: '工程',
      children: [
        { value: 'frontend', label: '前端' },
        { value: 'backend', label: '后端' },
      ],
    },
  ];
  return (
    <>
      <CfTreeSelect value={value} onChange={setValue} options={options} placeholder="紧凑:关闭引导线" showLines={false} default-expanded-keys="all" />
    </>
  );
}
import { useState } from 'react';
import { CfTreeSelect } from '@chufix-design/react';

export default function Demo() {
  const [value, setValue] = useState<string | undefined>(undefined);
  const options= [
    {
      value: 'design',
      label: '设计系统',
      children: [
        { value: 'tokens', label: 'Tokens' },
        { value: 'components', label: 'Components' },
      ],
    },
    {
      value: 'engineering',
      label: '工程',
      children: [
        { value: 'frontend', label: '前端' },
        { value: 'backend', label: '后端' },
      ],
    },
  ];
  return (
    <>
      <CfTreeSelect value={value} onChange={setValue} options={options} placeholder="紧凑:关闭引导线" showLines={false} default-expanded-keys="all" />
    </>
  );
}

API

属性类型默认值说明
optionsTreeSelectNode[]树节点列表
value / modelValuestring | string[]当前值;多选时为数组
placeholderstring请选择空值占位
multiplebooleanfalse多选
cascadebooleantrue多选时父节点点击是否级联选中后代
searchablebooleanfalse显示搜索输入;匹配会沿路径展开祖先
clearablebooleanfalse显示清空按钮
disabledbooleanfalse禁用
size'sm' | 'md' | 'lg''md'尺寸
defaultExpandedKeysstring[] | 'all'初始展开节点;'all' 全展开,未传则只显示根节点
showLinesbooleantrue显示层级引导线

Events

Vue 事件React 回调payload说明
update:modelValueonChange(value, node)选中变化;node 为最近点击的叶子节点(多选场景)
changeonChange(value, node)同上

TreeSelectNode

字段类型说明
valuestring唯一值
labelstring展示文本
disabledboolean禁用节点(级联也不会勾选)
childrenTreeSelectNode[]子节点

反馈与讨论

TreeSelect 树形选择 的讨论

0
0 / 600
正在加载评论...