npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

cvue-treeselect

v0.1.2

Published

A multi-select component with nested options support for Vue.js

Readme

TreeSelect 下拉树

树型选择器组件:支持单选、多选、懒加载(可支持搜索,自定义下拉框类名)、过滤数据、编辑信息时回显、判断当前节点是否需要禁用等功能

基础用法

:::demo

<template>
  <div>
    <ui-tree-select
      :options="options"
      placeholder="请选择你最喜欢的蔬菜或者水果"
      v-model="value"
    />
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: null,
        options: [
          {
            id: "fruits",
            label: "水果",
            children: [
              {
                id: "apple",
                label: "苹果 🍎",
              },
              {
                id: "grapes",
                label: "葡萄 🍇",
              },
              {
                id: "pear",
                label: "梨 🍐",
              },
              {
                id: "strawberry",
                label: "草莓 🍓",
              },
              {
                id: "watermelon",
                label: "西瓜 🍉",
              },
            ],
          },
          {
            id: "vegetables",
            label: "蔬菜",
            children: [
              {
                id: "corn",
                label: "玉米 🌽",
              },
              {
                id: "carrot",
                label: "胡萝卜 🥕",
              },
              {
                id: "eggplant",
                label: "茄子 🍆",
              },
              {
                id: "tomato",
                label: "番茄 🍅",
              },
            ],
          },
        ],
      };
    },
  };
</script>

:::

多选模式

通过设置 multiple 属性为 true 来启用多选模式。在多选模式下,v-model 的值是一个数组,包含所有选中节点的值。

:::demo

<template>
  <div>
    <ui-tree-select
      :options="options"
      :multiple="true"
      value-consists-of="ALL"
      placeholder="请选择多个你喜欢的蔬菜或者水果"
      v-model="value"
    />
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: [],
        options: [
          {
            id: "fruits",
            label: "水果",
            children: [
              {
                id: "apple",
                label: "苹果 🍎",
              },
              {
                id: "grapes",
                label: "葡萄 🍇",
              },
              {
                id: "pear",
                label: "梨 🍐",
              },
              {
                id: "strawberry",
                label: "草莓 🍓",
              },
              {
                id: "watermelon",
                label: "西瓜 🍉",
              },
            ],
          },
          {
            id: "vegetables",
            label: "蔬菜",
            children: [
              {
                id: "corn",
                label: "玉米 🌽",
              },
              {
                id: "carrot",
                label: "胡萝卜 🥕",
              },
              {
                id: "eggplant",
                label: "茄子 🍆",
              },
              {
                id: "tomato",
                label: "番茄 🍅",
              },
            ],
          },
        ],
      };
    },
  };
</script>

:::

更多特性

本示例展示了 TreeSelect 组件的多种配置选项,您可以通过勾选不同的选项来查看不同功能的效果。

:::demo

<template>
  <div>
    <div :dir="rtl ? 'rtl' : 'ltr'">
      <ui-tree-select
        name="demo"
        :multiple="multiple"
        :clearable="clearable"
        :searchable="searchable"
        :disabled="disabled"
        :open-on-click="openOnClick"
        :open-on-focus="openOnFocus"
        :clear-on-select="clearOnSelect"
        :close-on-select="closeOnSelect"
        :always-open="alwaysOpen"
        :append-to-body="appendToBody"
        :options="options"
        :limit="3"
        :max-height="200"
        v-model="value"
      />
    </div>
    <div class="value-display">当前值: {{ value }}</div>
    <div class="control-panel">
      <p>
        <label><input type="checkbox" v-model="multiple" />多选</label>
        <label><input type="checkbox" v-model="clearable" />可清空</label>
        <label><input type="checkbox" v-model="searchable" />可搜索</label>
        <label><input type="checkbox" v-model="disabled" />禁用</label>
      </p>
      <p>
        <label><input type="checkbox" v-model="openOnClick" />点击时打开</label>
        <label
          ><input type="checkbox" v-model="openOnFocus" />获取焦点时打开</label
        >
      </p>
      <p>
        <label
          ><input
            type="checkbox"
            v-model="clearOnSelect"
          />选择后清空搜索框</label
        >
        <label
          ><input
            type="checkbox"
            v-model="closeOnSelect"
          />选择后关闭菜单</label
        >
      </p>
      <p>
        <label><input type="checkbox" v-model="alwaysOpen" />始终打开</label>
        <label
          ><input type="checkbox" v-model="appendToBody" />附加到body</label
        >
        <label><input type="checkbox" v-model="rtl" />RTL模式</label>
      </p>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        multiple: true,
        clearable: true,
        searchable: true,
        disabled: false,
        openOnClick: true,
        openOnFocus: false,
        clearOnSelect: true,
        closeOnSelect: false,
        alwaysOpen: false,
        appendToBody: false,
        rtl: false,
        value: ["a"],
        options: [
          {
            id: "a",
            label: "选项A",
            children: [
              {
                id: "aa",
                label: "选项A-1",
              },
              {
                id: "ab",
                label: "选项A-2",
              },
            ],
          },
          {
            id: "b",
            label: "选项B",
            children: [
              {
                id: "ba",
                label: "选项B-1",
              },
            ],
          },
          {
            id: "c",
            label: "选项C",
            children: [
              {
                id: "ca",
                label: "选项C-1",
              },
            ],
          },
        ],
      };
    },
    watch: {
      multiple(newValue) {
        if (newValue) {
          this.value = this.value ? [this.value] : [];
        } else {
          this.value = this.value[0];
        }
      },
    },
  };
</script>

<style>
  .value-display {
    margin-top: 10px;
    padding: 8px 12px;
    background-color: #f5f7fa;
    border-radius: 4px;
    color: #5e6d82;
  }
  .control-panel {
    margin-top: 15px;
    padding: 12px;
    border: 1px solid #ebeef5;
    border-radius: 4px;
  }
  .control-panel label {
    margin-right: 15px;
    display: inline-flex;
    align-items: center;
  }
  .control-panel input[type="checkbox"] {
    margin-right: 5px;
  }
</style>

:::

通过上面的交互示例,您可以体验 TreeSelect 组件的以下特性:

  • 多选/单选模式切换
  • 可清空选项
  • 可搜索功能
  • 禁用状态
  • 点击/获取焦点时打开菜单
  • 选择后是否清空搜索框
  • 选择后是否关闭菜单
  • 始终保持菜单打开
  • 将菜单附加到 body 元素
  • RTL(从右到左)文本方向支持

禁用特定节点

通过在节点对象中设置 isDisabled: true,可以禁用特定的选项。被禁用的选项不可被选中,但仍然可以展开(如果是分支节点)。

:::demo

<template>
  <div>
    <ui-tree-select
      v-model="value"
      :multiple="true"
      :options="options"
      placeholder="请选择项目..."
    />
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: [],
        options: [
          {
            id: "projects",
            label: "项目",
            children: [
              {
                id: "frontend",
                label: "前端项目",
                children: [
                  {
                    id: "vue",
                    label: "Vue项目",
                  },
                  {
                    id: "react",
                    label: "React项目",
                    isDisabled: true, // 禁用此选项
                  },
                  {
                    id: "angular",
                    label: "Angular项目",
                  },
                ],
              },
              {
                id: "backend",
                label: "后端项目",
                isDisabled: true, // 禁用此选项及其所有子项
                children: [
                  {
                    id: "java",
                    label: "Java项目",
                  },
                  {
                    id: "python",
                    label: "Python项目",
                  },
                  {
                    id: "nodejs",
                    label: "Node.js项目",
                  },
                ],
              },
              {
                id: "mobile",
                label: "移动端项目",
                children: [
                  {
                    id: "ios",
                    label: "iOS项目",
                    isDisabled: true, // 禁用此选项
                  },
                  {
                    id: "android",
                    label: "Android项目",
                  },
                  {
                    id: "flutter",
                    label: "Flutter项目",
                  },
                ],
              },
            ],
          },
        ],
      };
    },
  };
</script>

:::

在上面的示例中:

  • "React 项目"作为叶子节点被禁用
  • "后端项目"作为分支节点被禁用,这意味着它的所有子节点也不可选择
  • "iOS 项目"作为叶子节点被禁用

延迟加载

如果您有大量深层嵌套的选项,您可能希望在初始加载时只加载最顶层的选项,并在需要时才加载其余部分。您可以通过以下步骤实现:

  1. 通过设置 children: null 声明一个未加载的分支节点
  2. 添加 loadOptions 属性
  3. 每当展开未加载的分支节点时,将调用 loadOptions({ action, parentNode, callback, instanceId }),然后您可以执行从远程服务器请求数据的任务

:::demo

<template>
  <div>
    <ui-tree-select
      :multiple="true"
      :options="options"
      :load-options="loadOptions"
      noChildrenText="没有子节点.."
      placeholder="展开任意文件夹选项..."
      v-model="value"
    />
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: null,
        options: [
          {
            id: "success",
            label: "包含子节点",
            // 声明一个未加载的分支节点
            children: null,
          },
          {
            id: "no-children",
            label: "没有子节点",
            children: null,
          },
          {
            id: "failure",
            label: "演示错误处理",
            children: null,
          },
        ],
      };
    },
    methods: {
      loadOptions({ action, parentNode, callback }) {
        // 通常,在这里执行AJAX操作
        // 服务器响应后,将子选项分配给父节点并调用回调函数

        // 模拟异步操作,而不是请求真实的API服务器(仅用于演示)
        const simulateAsyncOperation = (fn) => {
          setTimeout(fn, 2000);
        };

        if (action === "LOAD_CHILDREN_OPTIONS") {
          switch (parentNode.id) {
            case "success": {
              simulateAsyncOperation(() => {
                parentNode.children = [
                  {
                    id: "child",
                    label: "子选项",
                  },
                ];
                callback();
              });
              break;
            }
            case "no-children": {
              simulateAsyncOperation(() => {
                parentNode.children = [];
                callback();
              });
              break;
            }
            case "failure": {
              simulateAsyncOperation(() => {
                callback(new Error("加载选项失败:网络错误。"));
              });
              break;
            }
            default: /* empty */
          }
        }
      },
    },
  };
</script>

:::

懒加载模式下的回填

有时候,我们需要在懒加载模式下预先选中某些值,即使那些节点所在的分支尚未加载。TreeSelect 组件可以通过设置初始 v-model 的值来实现回填功能。

:::demo

<template>
  <div>
    <ui-tree-select
      :multiple="true"
      :options="options"
      :load-options="loadOptions"
      :default-options="defaultOptions"
      placeholder="展示懒加载+回填功能"
      v-model="value"
    >
    </ui-tree-select>
    <div class="value-display">当前选中值: {{ value }}</div>
    <div class="action-buttons">
      <button class="demo-button" @click="resetSelection">重置选择</button>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: ["1", "2"],
        defaultOptions: [
          { id: "1", label: "南京市" },
          { id: "2", label: "苏州市" },
        ],
        options: [
          {
            id: "region-1",
            label: "华东地区",
            children: null,
          },
          {
            id: "region-2",
            label: "华南地区",
            children: null,
          },
          {
            id: "region-3",
            label: "华北地区",
            children: null,
          },
        ],
      };
    },
    methods: {
      loadOptions({ action, parentNode, callback }) {
        // 模拟异步加载
        const simulateAsyncOperation = (fn) => {
          setTimeout(fn, 1000);
        };

        if (action === "LOAD_CHILDREN_OPTIONS") {
          simulateAsyncOperation(() => {
            console.log("Loading children for:", parentNode.id);

            // 根据节点ID生成不同的子节点
            if (parentNode.id === "region-1") {
              parentNode.children = [
                { id: "1", label: "南京市" },
                { id: "2", label: "苏州市" },
                { id: "3", label: "杭州市" },
                { id: "4", label: "上海市" },
              ];
              callback();
            } else if (parentNode.id === "region-2") {
              parentNode.children = [
                { id: "5", label: "广州市" },
                { id: "6", label: "深圳市" },
                { id: "7", label: "东莞市" },
              ];
              callback();
            } else if (parentNode.id === "region-3") {
              parentNode.children = [
                { id: "8", label: "北京市" },
                { id: "9", label: "天津市" },
              ];
              callback();
            } else {
              callback();
            }
          });
        }
      },
      resetSelection() {
        this.value = [];
      },
    },
  };
</script>

<style>
  .action-buttons {
    margin-top: 15px;
    display: flex;
    gap: 10px;
  }
  .demo-button {
    padding: 8px 15px;
    background-color: #409eff;
    border: none;
    color: white;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
  }
  .demo-button:hover {
    background-color: #66b1ff;
  }
</style>

:::

在上面的示例中,我们演示了如何在懒加载模式下实现回填功能:

  1. 树形结构设计:通过 children: null 声明未加载的分支节点,构建了一个地区-城市的懒加载树。

  2. 回填机制:我们使用 defaultOptions 属性来解决回填时的标签显示问题:

    • 使用 defaultOptions 属性
      • 提供一个默认选项数组,包含 ID 和标签信息
      • 在组件初始化时,虽然树节点还未加载,但通过 defaultOptions 可以正确显示已选项的标签
      • 这种方式适用于不想修改 value 格式(保持为 ID 数组)的场景
  3. 懒加载处理:当用户展开相关分支时,TreeSelect 组件会根据 loadOptions 函数加载必要的节点,并正确显示选中状态。

注意:除了使用 defaultOptions 外,还可以使用 value-format="object" 并将 v-model 绑定的值设置为对象数组(每个对象包含 idlabel 属性)来解决懒加载回填时的标签显示问题。这种方式直接提供了节点的标签信息,不依赖于节点的加载状态。

异步搜索

TreeSelect 支持根据用户输入动态加载和更改整个选项列表。默认情况下,TreeSelect 会缓存每个 AJAX 请求的结果,从而使用户的等待时间更少。

:::demo

<template>
  <div>
    <ui-tree-select
      :multiple="true"
      :async="true"
      :load-options="loadOptions"
      :defaultOptions="defaultOptions"
      searchPromptText="请输入关键字搜索"
      placeholder="请输入关键字搜索"
      v-model="value"
    />
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: ["1"],
        defaultOptions: [{ id: "1", label: "方法1" }],
      };
    },
    methods: {
      loadOptions({ action, searchQuery, callback }) {
        // 模拟异步操作
        const simulateAsyncOperation = (fn) => {
          setTimeout(fn, 2000);
        };

        if (action === "ASYNC_SEARCH") {
          simulateAsyncOperation(() => {
            // 根据搜索词生成选项
            const options = [1, 2, 3, 4, 5].map((i) => ({
              id: `${searchQuery}-${i}`,
              label: `${searchQuery}-${i}`,
            }));
            callback(null, options);
          });
        }
      },
    },
  };
</script>

:::

多选模式下的值控制

在多选模式下,您可以通过 value-consists-of 属性控制 v-model 绑定值中应包含哪些节点。这对于确定选中状态的表现方式和数据提交格式至关重要。

:::demo

<template>
  <div>
    <ui-tree-select
      :options="options"
      :multiple="true"
      :value-consists-of="valueConsistsOf"
      placeholder="请选择多个选项..."
      v-model="value"
    />
    <div class="value-display">当前值: {{ value }}</div>
    <p><strong>值包含模式:</strong></p>
    <div class="value-mode-options">
      <label
        ><input
          type="radio"
          value="BRANCH_PRIORITY"
          v-model="valueConsistsOf"
        />BRANCH_PRIORITY - 分支节点优先</label
      >
      <label
        ><input
          type="radio"
          value="LEAF_PRIORITY"
          v-model="valueConsistsOf"
        />LEAF_PRIORITY - 叶子节点优先</label
      >
      <label
        ><input type="radio" value="ALL" v-model="valueConsistsOf" />ALL -
        包含所有选中节点</label
      >
      <label
        ><input
          type="radio"
          value="ALL_WITH_INDETERMINATE"
          v-model="valueConsistsOf"
        />ALL_WITH_INDETERMINATE - 包含所有节点(含不确定状态)</label
      >
    </div>
    <div class="usage-scenarios">
      <p><strong>应用场景:</strong></p>
      <ul>
        <li>
          <strong>BRANCH_PRIORITY</strong>:
          适合权限配置、组织结构选择等场景,优先使用上级概念,数据更简洁
        </li>
        <li>
          <strong>LEAF_PRIORITY</strong>:
          适合商品选择、文件选择等场景,关注具体末端项目而非类别
        </li>
        <li>
          <strong>ALL</strong>:
          适合需要完整数据路径的表单提交,或需要显示完整选择路径的场景
        </li>
        <li>
          <strong>ALL_WITH_INDETERMINATE</strong>:
          适合需要保存精确选择状态并在后续恢复的复杂表单
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: [],
        valueConsistsOf: "BRANCH_PRIORITY",
        options: [
          {
            id: "categories",
            label: "商品类别",
            children: [
              {
                id: "electronics",
                label: "电子产品",
                children: [
                  {
                    id: "phones",
                    label: "手机",
                  },
                  {
                    id: "laptops",
                    label: "笔记本电脑",
                  },
                  {
                    id: "tablets",
                    label: "平板电脑",
                  },
                ],
              },
              {
                id: "clothing",
                label: "服装",
                children: [
                  {
                    id: "mens",
                    label: "男装",
                  },
                  {
                    id: "womens",
                    label: "女装",
                  },
                ],
              },
            ],
          },
        ],
      };
    },
  };
</script>

<style>
  .value-display {
    margin-top: 10px;
    padding: 8px 12px;
    background-color: #f5f7fa;
    border-radius: 4px;
    color: #5e6d82;
    word-break: break-all;
  }
  .value-mode-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 15px;
  }
  .value-mode-options label {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
  }
  .value-mode-options input {
    margin-right: 5px;
  }
  .usage-scenarios {
    margin-top: 15px;
    padding: 12px;
    border: 1px solid #ebeef5;
    border-radius: 4px;
    background-color: #fafbfc;
  }
  .usage-scenarios ul {
    padding-left: 18px;
    margin: 8px 0;
  }
  .usage-scenarios li {
    margin-bottom: 8px;
    line-height: 1.5;
  }
</style>

:::

value-consists-of 参数决定了多选模式下,当选中树节点时 v-model 绑定值中包含哪些节点 ID:

  1. BRANCH_PRIORITY (默认) - 优先选择分支节点

    • 当选中一个分支节点时,该节点会被添加到 value 中,但其子节点不会被包含
    • 当一个分支节点的所有子节点都被选中时,只有父节点会出现在 value 中
    • 这种模式简化了数据结构,使 value 数组更简洁
  2. LEAF_PRIORITY - 优先选择叶子节点

    • 当一个分支的所有叶子节点被选中时,value 中只包含这些叶子节点 ID,而不包含分支节点
    • 适用于需要具体收集末端数据项的场景
  3. ALL - 包含所有选中节点

    • 当选中一个节点时,该节点及其所有选中的子节点 ID 都会被包含在 value 中
    • 提供最完整的选择数据,适合需要知道完整选择路径的场景
  4. ALL_WITH_INDETERMINATE - 包含所有节点及不确定状态节点

    • 与 ALL 类似,但还包括处于"不确定"状态的节点(即部分子节点被选中的分支节点)
    • 这是最全面的选择模式,提供了选择树的完整状态信息

扁平模式(父子不关联)与排序

在之前的所有示例中,我们使用了 TreeSelect 的默认非扁平模式,这意味着:

  • 当选中一个分支节点时,其所有子节点也会被选中
  • 当一个分支节点的所有子节点都被选中时,该分支节点本身也会被选中

有时我们不需要这种机制,希望分支节点和叶子节点不相互影响。在这种情况下,应该使用扁平模式,如下所示。

如果您想控制所选选项的显示顺序,请使用 sortValueBy 属性。该属性有三个选项:

  • "ORDER_SELECTED" (默认) - 按选择顺序
  • "LEVEL" - 按选项级别:C 🡒 BB 🡒 AAA
  • "INDEX" - 按选项索引:AAA 🡒 BB 🡒 C

:::demo

<template>
  <div>
    <ui-tree-select
      :multiple="true"
      :options="options"
      :flat="true"
      :sort-value-by="sortValueBy"
      :default-expand-level="1"
      placeholder="尝试选择一些选项"
      v-model="value"
    />
    <div class="value-display">当前值: {{ value }}</div>
    <p><strong>排序方式:</strong></p>
    <div class="sort-options">
      <label
        ><input
          type="radio"
          value="ORDER_SELECTED"
          v-model="sortValueBy"
        />按选择顺序</label
      >
      <label
        ><input type="radio" value="LEVEL" v-model="sortValueBy" />按级别</label
      >
      <label
        ><input type="radio" value="INDEX" v-model="sortValueBy" />按索引</label
      >
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        value: ["c", "aaa", "bb"],
        options: [
          {
            id: "a",
            label: "A",
            children: [
              {
                id: "aa",
                label: "AA",
                children: [
                  {
                    id: "aaa",
                    label: "AAA",
                  },
                  {
                    id: "aab",
                    label: "AAB",
                  },
                ],
              },
              {
                id: "ab",
                label: "AB",
              },
              {
                id: "ac",
                label: "AC",
              },
            ],
          },
          {
            id: "b",
            label: "B",
            children: [
              {
                id: "ba",
                label: "BA",
              },
              {
                id: "bb",
                label: "BB",
              },
            ],
          },
          {
            id: "c",
            label: "C",
          },
        ],
        sortValueBy: "ORDER_SELECTED",
      };
    },
  };
</script>

<style>
  .value-display {
    margin-top: 10px;
    padding: 8px 12px;
    background-color: #f5f7fa;
    border-radius: 4px;
    color: #5e6d82;
  }
  .sort-options {
    display: flex;
    gap: 20px;
  }
  .sort-options label {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
  }
  .sort-options input {
    margin-right: 5px;
  }
</style>

:::

基本特性

此示例展示了 vue-treeselect 最常用的功能。通过输入几个字母可以尝试模糊匹配功能。

首先您需要学习如何定义选项。有两种类型的选项:a. 文件夹选项,可折叠且可能有子选项;b. 普通选项,不可折叠且没有子选项。这里,我们借用计算机科学的基本概念,将前者称为分支节点,后者称为叶子节点。这两种节点共同组成了树结构。

定义叶子节点非常简单:

{
  id: '<id>', // 用于在树中标识选项,因此其值在所有选项中必须是唯一的
  label: '<label>', // 用于显示选项
}

定义分支节点只需一个额外的 children 属性:

{
  id: '<id>',
  label: '<label>',
  children: [
    {
      id: '<child id>',
      label: '<child label>',
    },
    ...
  ],
}

然后,您可以将这些节点的数组作为 options 属性传递。请注意,即使您为 children 属性分配了一个空数组,它仍被视为分支节点。这可能与您在计算机科学中学到的不同,在计算机科学中,没有子节点的节点通常被称为叶子节点。

有关节点对象中所有可用属性的信息,请参见下文。

TreeSelect 属性

| 参数 | 说明 | 类型 | 可选值 | 默认值 | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------- | --------------------------------------- | | allowClearingDisabled | 是否允许在有禁用选中节点的情况下重置值 | Boolean | - | false | | allowSelectingDisabledDescendants | 当选中/取消选中祖先节点时,是否应选中/取消选中其禁用的后代节点。您可能希望与 allowClearingDisabled 属性一起使用 | Boolean | - | false | | alwaysOpen | 菜单是否应始终打开 | Boolean | - | false | | appendToBody | 将菜单附加到 <body /> | Boolean | - | false | | async | 是否启用异步搜索模式 | Boolean | - | false | | autoFocus | 在组件加载时自动聚焦 | Boolean | - | false | | autoLoadRootOptions | 在组件加载时自动加载根选项。设置为 false 时,仅在打开菜单时加载根选项 | Boolean | - | true | | autoDeselectAncestors | 当用户取消选择节点时,自动取消选择其祖先节点。仅适用于平面模式 | Boolean | - | false | | autoDeselectDescendants | 当用户取消选择节点时,自动取消选择其后代节点。仅适用于平面模式 | Boolean | - | false | | autoSelectAncestors | 当用户选择节点时,自动选择其祖先节点。仅适用于平面模式 | Boolean | - | false | | autoSelectDescendants | 当用户选择节点时,自动选择其后代节点。仅适用于平面模式 | Boolean | - | false | | backspaceRemoves | 如果没有文本输入,按 Backspace 是否删除最后一项 | Boolean | - | true | | beforeClearAll | 在清除所有输入字段之前处理的函数。返回 false 可阻止值被清除 | Function | - | () => true | | branchNodesFirst | 在叶子节点之前显示分支节点 | Boolean | - | false | | cacheOptions | 是否缓存异步搜索模式的每个搜索请求的结果 | Boolean | - | true | | clearable | 是否显示一个"×"按钮来重置值 | Boolean | - | true | | clearAllText | 多选模式下"×"按钮的标题 | String | - | "清除所有" | | clearOnSelect | 选择选项后是否清除搜索输入。仅在多选模式下使用。对于单选模式,无论属性值如何,选择后始终清除输入 | Boolean | - | 多选模式下默认为 false,否则始终为 true | | clearValueText | "×"按钮的标题 | String | - | "清除值" | | closeOnSelect | 选择选项后是否关闭菜单。仅在多选模式下使用 | Boolean | - | true | | defaultExpandLevel | 加载时应自动展开的分支节点的级别数。设置为 Infinity 可使所有分支节点默认展开 | Number | - | 0 | | defaultOptions | 用户开始搜索前显示的默认选项集。用于异步搜索模式。设置为 true 时,将自动加载空字符串搜索查询的结果 | Boolean/Array | - | false | | deleteRemoves | 如果没有文本输入,按 Delete 是否删除最后一项 | Boolean | - | true | | delimiter | 用于连接多个值作为隐藏字段值的分隔符 | String | - | "," | | flattenSearchResults | 搜索时是否扁平化树(仅限同步搜索模式) | Boolean | - | false | | disableBranchNodes | 是否阻止选择分支节点 | Boolean | - | false | | disabled | 是否禁用控件 | Boolean | - | false | | disableFuzzyMatching | 设置为 true 可禁用默认启用的模糊匹配功能 | Boolean | - | false | | flat | 是否启用平面模式 | Boolean | - | false | | instanceId | 将与所有事件一起作为最后一个参数传递。用于识别事件来源 | String/Number | - | "<自动递增数字>$$" | | joinValues | 使用 delimiter 将多个值连接到单个表单字段中(传统模式) | Boolean | - | false | | limit | 限制显示选定选项的数量。其余将隐藏在 limitText 字符串中 | Number | - | Infinity | | limitText | 处理超过定义限制时显示消息的函数 | Function | - | count => 和${count}个更多 | | loadingText | 加载选项时显示的文本 | String | - | "加载中..." | | loadOptions | 用于动态加载选项 | Function | - | - | | matchKeys | 用于过滤 node 对象的键 | Array | - | [ "label" ] | | maxHeight | 设置菜单的 maxHeight 样式值 | Number | - | 300 | | multiple | 设置为 true 允许选择多个选项(又称多选模式) | Boolean | - | false | | name | 为 HTML 表单生成带有此字段名的隐藏 <input /> 标签 | String | - | - | | noChildrenText | 当分支节点没有子节点时显示的文本 | String | - | "没有子选项。" | | noOptionsText | 没有可用选项时显示的文本 | String | - | "没有可用选项。" | | noResultsText | 没有匹配的搜索结果时显示的文本 | String | - | "未找到结果..." | | normalizer | 用于标准化源数据 | Function | - | node => node | | openDirection | 菜单打开的方向,默认("auto")下,菜单将在控件下方打开。如果没有足够空间,vue-treeselect 将自动翻转菜单 | String | "auto", "below", "bottom", "above", "top" | "auto" | | openOnClick | 是否在点击控件时自动打开菜单 | Boolean | - | true | | openOnFocus | 是否在控件获得焦点时自动打开菜单 | Boolean | - | false | | options | 可用选项数组 | Array | - | - | | placeholder | 字段占位符,在没有值时显示 | String | - | "选择..." | | required | 在需要时应用 HTML5 required 属性 | Boolean | - | false | | retryText | 询问用户是否重试加载子选项时显示的文本 | String | - | "重试?" | | retryTitle | 重试按钮的标题 | String | - | "点击重试" | | searchable | 是否启用搜索功能 | Boolean | - | true | | searchNested | 如果搜索查询也应在所有祖先节点中搜索,则设置为 true | Boolean | - | false | | searchPromptText | 提示异步搜索的提示文本 | String | - | "输入搜索..." | | showCount | 是否在每个分支节点的标签旁边显示子节点计数 | Boolean | - | false | | showCountOf | 与 showCount 一起使用,指定应显示哪种类型的计数 | String | "ALL_CHILDREN", "ALL_DESCENDANTS", "LEAF_CHILDREN", "LEAF_DESCENDANTS" | "ALL_CHILDREN" | | showCountOnSearch | 搜索时是否显示子节点计数。未指定时回退到 showCount 的值 | Boolean | - | - | | sortValueBy | 选定选项在触发器中显示的顺序以及在 value 数组中排序的顺序。仅在多选模式下使用 | String | "ORDER_SELECTED", "LEVEL", "INDEX" | "ORDER_SELECTED" | | tabIndex | 控件的 Tab 索引 | Number | - | 0 | | value | 控件的值。当 :multiple="false" 时应为 idnode 对象;当 :multiple="true" 时应为 idnode 对象数组 | id/node/id[]/node[] | - | - | | valueConsistsOf | 多选模式下 value 数组中应包含哪种类型的节点 | String | "ALL", "BRANCH_PRIORITY", "LEAF_PRIORITY", "ALL_WITH_INDETERMINATE" | "BRANCH_PRIORITY" | | valueFormat | value 属性的格式。注意,当设置为 "object" 时,value 中每个 node 对象仅需要 idlabel 属性 | String | "id", "object" | "id" | | zIndex | 菜单的 z-index | Number/String | - | 999 |

TreeSelect 事件

| 事件名称 | 说明 | 回调参数 | | ------------- | ---------------------- | ------------------------------------------------- | | open | 菜单打开时触发 | (instanceId) 实例 ID | | close | 菜单关闭时触发 | (value, instanceId) 当前值,实例 ID | | input | 值变化后触发 | (value, instanceId) 当前值,实例 ID | | select | 选择某个选项后触发 | (node, instanceId) 所选节点,实例 ID | | deselect | 取消选择某个选项后触发 | (node, instanceId) 取消选择的节点,实例 ID | | search-change | 搜索查询变化后触发 | (searchQuery, instanceId) 搜索查询字符串,实例 ID |

节点对象属性

以下是节点对象可用的属性。

| 属性 | 类型 | 说明 | | ----------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | id (必填) | Number / String | 用于在树中标识选项,其值在所有选项中必须是唯一的 | | label (必填) | String | 用于显示选项 | | children | node[] / null | 声明一个分支节点。您可以:1) 设置为由 a.叶子节点,b.分支节点,或 c.这两者混合组成的子选项数组2) 设置为空数组表示没有子选项3) 设置为 null 以声明一个未加载的分支节点,用于延迟加载。您可以稍后在 loadOptions() 中重新分配一个数组(无论是否为空)来注册这些子选项,并将此分支节点标记为已加载如果要声明叶子节点,设置 children: undefined 或简单地省略此属性 | | isDisabled | Boolean | 用于禁用项目选择 | | isNew | Boolean | 用于给新节点不同的颜色 | | isDefaultExpanded | Boolean | 此文件夹选项是否应默认展开 |

labelchildrenisDisabled 的值可以随时重新分配。

除了上述列出的属性外,还可以添加更多属性。您甚至可以通过访问 node.raw.xxx 在自定义模板中使用这些额外的属性。

TreeSelect 插槽

| 插槽名 | 参数 | 说明 | | ------------ | ---------------------------------------------------------------- | ------------------------ | | option-label | { node, shouldShowCount, count, labelClassName, countClassName } | 自定义选项标签模板的插槽 | | value-label | { node } | 自定义值标签模板的插槽 | | before-list | - | 显示在菜单列表之前的插槽 | | after-list | - | 显示在菜单列表之后的插槽 |