Skip to content

🌳 TreeSelect 分类选择 - 层次分明的选择体验!

🎯 分类选择专家:让复杂的层级数据选择变得简单直观,左右分栏设计让用户一目了然!

✨ 什么是 TreeSelect?

TreeSelect 是一个专为层级数据设计的选择组件,就像一个智能的文件管理器,左侧显示分类导航,右侧展示具体选项。无论是城市选择、商品分类,还是组织架构,都能轻松应对!

🎯 核心特色

  • 🏗️ 层级清晰:左右分栏设计,层次分明
  • 🎨 交互友好:支持单选、多选模式
  • 🔍 快速定位:左侧导航快速切换分类
  • 🎭 高度定制:支持徽标、禁用、自定义内容

📦 引入组件

通过以下方式来全局注册组件,更多注册方式请参考组件注册

js
import { createApp } from 'vue';
import { TreeSelect } from 'vant';

const app = createApp();
app.use(TreeSelect);

🚀 代码演示

🎯 单选模式

最经典的单选模式,适用于城市选择、商品分类等场景。左侧导航快速切换分类,右侧选择具体选项:

html
<van-tree-select
  v-model:active-id="activeId"
  v-model:main-active-index="activeIndex"
  :items="items"
  @click-nav="onClickNav"
  @click-item="onClickItem"
/>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const activeId = ref(1);
    const activeIndex = ref(0);
    
    // 🏙️ 城市数据结构
    const items = [
      {
        text: '浙江省',
        children: [
          { text: '杭州市', id: 1 },
          { text: '温州市', id: 2 },
          { text: '宁波市', id: 3, disabled: true }, // 🚫 禁用选项
        ],
      },
      {
        text: '江苏省',
        children: [
          { text: '南京市', id: 4 },
          { text: '无锡市', id: 5 },
          { text: '徐州市', id: 6 },
        ],
      },
      {
        text: '福建省',
        disabled: true, // 🚫 整个分类禁用
      },
    ];

    // 🎯 导航点击事件
    const onClickNav = (index) => {
      showToast(`切换到分类: ${items[index].text}`);
    };

    // 🎯 选项点击事件
    const onClickItem = (item) => {
      showToast(`选择了: ${item.text}`);
    };

    return {
      items,
      activeId,
      activeIndex,
      onClickNav,
      onClickItem,
    };
  },
};

🎨 多选模式

支持同时选择多个选项,适用于多城市配送、多分类筛选等场景:

html
<van-tree-select
  v-model:active-id="activeIds"
  v-model:main-active-index="activeIndex"
  :items="items"
  :max="3"
  @click-item="onClickItem"
/>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const activeIds = ref([1, 2]); // 🎯 数组格式支持多选
    const activeIndex = ref(0);
    
    // 🏪 商品分类数据
    const items = [
      {
        text: '数码产品',
        children: [
          { text: '智能手机', id: 1 },
          { text: '平板电脑', id: 2 },
          { text: '笔记本电脑', id: 3, disabled: true },
        ],
      },
      {
        text: '家用电器',
        children: [
          { text: '电视机', id: 4 },
          { text: '洗衣机', id: 5 },
          { text: '冰箱', id: 6 },
        ],
      },
      {
        text: '服装鞋帽',
        disabled: true,
      },
    ];

    // 🎯 选项点击事件
    const onClickItem = (item) => {
      const isSelected = activeIds.value.includes(item.id);
      const action = isSelected ? '取消选择' : '选择';
      showToast(`${action}: ${item.text}`);
    };

    return {
      items,
      activeIds,
      activeIndex,
      onClickItem,
    };
  },
};

🎭 自定义内容

通过 content 插槽可以完全自定义右侧区域的内容,适用于展示复杂信息、图表或其他组件:

html
<van-tree-select
  v-model:main-active-index="activeIndex"
  :items="items"
  height="300px"
>
  <template #content>
    <div class="custom-content">
      <div class="content-header">
        <h3>🎨 自定义内容区域</h3>
        <p>当前选择: {{ items[activeIndex]?.text }}</p>
      </div>
      
      <div class="content-body">
        <van-cell-group>
          <van-cell title="📊 数据统计" value="查看详情" is-link />
          <van-cell title="📈 趋势分析" value="查看报告" is-link />
          <van-cell title="⚙️ 配置管理" value="进入设置" is-link />
        </van-cell-group>
      </div>
      
      <div class="content-footer">
        <van-button type="primary" block>
          确认选择 {{ items[activeIndex]?.text }}
        </van-button>
      </div>
    </div>
  </template>
</van-tree-select>
js
import { ref } from 'vue';

export default {
  setup() {
    const activeIndex = ref(0);
    
    // 🎯 功能分组数据
    const items = [
      { text: '📊 数据分析' },
      { text: '👥 用户管理' },
      { text: '⚙️ 系统设置' },
      { text: '📱 移动端' },
    ];

    return {
      activeIndex,
      items,
    };
  },
};
css
.custom-content {
  padding: 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.content-header {
  margin-bottom: 16px;
}

.content-header h3 {
  margin: 0 0 8px 0;
  color: #323233;
}

.content-header p {
  margin: 0;
  color: #969799;
  font-size: 14px;
}

.content-body {
  flex: 1;
  margin-bottom: 16px;
}

.content-footer {
  margin-top: auto;
}

🏷️ 徽标提示

通过 dotbadge 属性为分类添加提示信息,让用户快速了解每个分类的状态:

html
<van-tree-select
  v-model:active-id="activeId"
  v-model:main-active-index="activeIndex"
  :items="items"
  @click-item="onClickItem"
/>
js
import { ref } from 'vue';
import { showToast } from 'vant';

export default {
  setup() {
    const activeId = ref(1);
    const activeIndex = ref(0);
    
    // 🏷️ 带徽标的分类数据
    const items = [
      {
        text: '热门城市',
        dot: true, // 🔴 显示小红点
        children: [
          { text: '北京市', id: 1 },
          { text: '上海市', id: 2 },
          { text: '深圳市', id: 3 },
        ],
      },
      {
        text: '推荐城市',
        badge: 5, // 🏷️ 显示数字徽标
        children: [
          { text: '杭州市', id: 4 },
          { text: '南京市', id: 5 },
          { text: '苏州市', id: 6 },
        ],
      },
      {
        text: '其他城市',
        badge: 'NEW', // 🆕 显示文字徽标
        children: [
          { text: '成都市', id: 7 },
          { text: '重庆市', id: 8 },
          { text: '西安市', id: 9 },
        ],
      },
    ];

    // 🎯 选项点击事件
    const onClickItem = (item) => {
      showToast(`选择了: ${item.text}`);
    };

    return {
      activeId,
      activeIndex,
      items,
      onClickItem,
    };
  },
};

📚 API 参考

⚙️ Props

参数说明类型默认值
v-model:main-active-index 🎯左侧选中项的索引 - 控制当前激活的分类number | string0
v-model:active-id 🎨右侧选中项的 id - 支持单选(数字)和多选(数组)number | string | (number | string)[]0
items 📋分类显示所需的数据 - 树形结构的选项数据TreeSelectItem[][]
height 📏组件高度 - 默认单位为 px,支持百分比number | string300
max 🔢右侧项最大选中个数 - 多选模式下的限制number | stringInfinity
selected-icon ✅自定义右侧栏选中状态的图标 - 个性化选中标识stringsuccess

🎯 Events

事件名说明回调参数
click-nav 🧭点击左侧导航时触发 - 分类切换事件index: number
click-item 🎯点击右侧选择项时触发 - 选项选择事件item: TreeSelectChild

🎭 Slots

名称说明参数
nav-text 📝自定义导航名称 - 个性化左侧分类显示 v4.1.0item: TreeSelectChild
content 🎨自定义右侧区域内容 - 完全自定义右侧展示区域-

🏗️ TreeSelectItem 数据结构

TreeSelectItem 整体为一个数组,数组内包含一系列描述分类的对象,每个分类里,text 表示当前分类的名称,children 表示分类里的可选项。

js
[
  {
    // 导航名称
    text: '所有城市',
    // 导航名称右上角徽标
    badge: 3,
    // 是否在导航名称右上角显示小红点
    dot: true,
    // 导航节点额外类名
    className: 'my-class',
    // 该导航下所有的可选项
    children: [
      {
        // 名称
        text: '温州',
        // id,作为匹配选中状态的标识符
        id: 1,
        // 禁用选项
        disabled: true,
      },
      {
        text: '杭州',
        id: 2,
      },
    ],
  },
];
键名说明类型
text 📝导航名称 - 左侧分类显示的文字string
children 👶该导航下的可选项数据 - 右侧选项列表TreeSelectChild[]
className 🎨为对应的导航添加额外的 CSS 类名 - 自定义样式string
dot 🔴是否在导航右上角显示小红点 - 提醒标识boolean
badge 🏷️在导航右上角显示的徽标数字或文字 - 数量提示number | string
disabled 🚫是否禁用该导航 - 不可点击状态boolean

🧩 TreeSelectChild 数据结构

键名说明类型
id 🆔该选项的唯一标识符 - 用于选中状态管理number | string
text 📝选项文字 - 右侧选项显示的内容string
disabled 🚫是否禁用该选项 - 不可选择状态boolean

🔧 类型定义

组件导出以下类型定义:

ts
import type { TreeSelectItem, TreeSelectChild, TreeSelectProps } from 'vant';

🎨 主题定制

🎭 样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件

名称默认值描述
--van-tree-select-font-size 📝var(--van-font-size-md)字体大小
--van-tree-select-nav-background 🎨var(--van-background)左侧导航背景色
--van-tree-select-content-background 🖼️var(--van-background-2)右侧内容背景色
--van-tree-select-nav-item-padding 📏14px var(--van-padding-sm)导航项内边距
--van-tree-select-item-height 📐48px选项高度
--van-tree-select-item-active-color 🎯var(--van-primary-color)激活状态颜色
--van-tree-select-item-disabled-color 🚫var(--van-gray-5)禁用状态颜色
--van-tree-select-item-selected-size ✅16px选中图标大小

📖 相关文档

🎯 选择器组件

📋 列表组件

🎨 展示组件

🔧 工具组件

基於Vant構建的企業級移動端解決方案