TreeSelect

当选项的层级多深时,使用树形选择器比普通选择器更适合

提示

你也可以选择 ElTreeSelect 替代这个组件

使用

基础用法

传入 data 数据,生成树形结构 (格式同 Select 分组)

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    clearable
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref('')
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

控制不可选项目

将传入 data 数据中的某项设置为 disabled: true 即可

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref('')
    const data = ref([
      {
        label: '1',
        value: 1,
        disabled: true,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            disabled: true,
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1', disabled: true }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1', disabled: true }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

配置绑定数据键值

通过 config 配置数据键值。value- v-model 绑定的键值、label-显示键值、disabled-控制不可选的键值、children-子节点的键值

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    :config="config"
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref('')
    const config = ref({ value: 'label', label: 'value' })
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      config,
      data,
    }
  },
})
</script>
显示代码

开启多选

multipletrue 时,启用多选。此时绑定的 model-value 为数组格式

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    multiple
    clearable
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

隐藏多余标签

默认情况下选中值会以 Tag 的形式展现,你也可以设置 collapse-tags 属性将它们合并为一段文字。 您可以使用 collapse-tags-tooltip 属性来启用鼠标悬停折叠文字以显示具体所选值的行为

collapse-tags:
collapse-tags-tooltip:
<template>
  <div>
    <span>collapse-tags: </span>
    <pro-tree-select
      v-model="select"
      :data="data"
      multiple
      collapse-tags
    />
  </div>
  <div>
    <span>collapse-tags-tooltip: </span>
    <pro-tree-select
      v-model="select"
      :data="data"
      multiple
      collapse-tags
      collapse-tags-tooltip
    />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

多选控制不可选项目

同单选只需将传入 data 数据中的某项设置为 disabled: true 即可

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    multiple
    default-expand-all
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        disabled: true,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            disabled: true,
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1', disabled: true }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1', disabled: true }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

多选父子节点互不关联

check-strictlytrue 时,父子节点互不关联

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    multiple
    check-strictly
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

只选取子节点

only-select-leaftrue 时,只会选取子节点的数据

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    multiple
    only-select-leaf
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

自定义节点显示

通过 default 插槽可以定义内容。注意:在单选模式下需要参考下面内容自定义 class 实现控制不可选项目样式

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
  >
    <template #default="{ node, item, multiple }">
      <p
        :class="node.disabled && !multiple ? 'is-disabled' : ''"
        class="custom-tree-node"
      >
        <span>{{ item.label }}</span>
        <em>{{ item.value }}</em>
      </p>
    </template>
  </pro-tree-select>
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref('')
    const data = ref([
      {
        label: '1',
        value: 1,
        disabled: true,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            disabled: true,
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1', disabled: true }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1', disabled: true }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>

<style>
.custom-tree-node {
  flex: 1;
  display: flex;
  justify-content: space-between;
}
.custom-tree-node em {
  padding-right: 15px;
}
</style>
显示代码

选择节点过滤

filterabletrue 时,启用选择节点过滤。在选择框中输入文本,将过滤节点内容

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    multiple
    filterable
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = ref([
      {
        label: '1',
        value: 1,
        children: [
          {
            value: 11,
            label: '1-1',
            children: [{ value: 111, label: '1-1-1' }],
          },
        ],
      },
      {
        value: 2,
        label: '2',
        children: [
          {
            value: 21,
            label: '2-1',
            children: [{ value: 211, label: '2-1-1' }],
          },
          {
            value: 22,
            label: '2-2',
            children: [{ value: 221, label: '2-2-1' }],
          },
        ],
      },
      {
        value: 3,
        label: '3',
        children: [
          {
            value: 31,
            label: '3-1',
            children: [{ value: 311, label: '3-1-1' }],
          },
          {
            value: 32,
            label: '3-2',
            children: [{ value: 321, label: '3-2-1' }],
          },
        ],
      },
    ])

    return {
      select,
      data,
    }
  },
})
</script>
显示代码

懒加载

ElTree 一样,配置 lazy load 即可使用懒加载数据

<template>
  <pro-tree-select
    v-model="select"
    :data="data"
    :load="loadNode"
    lazy
    multiple
    filterable
  />
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  setup() {
    const select = ref([])
    const data = []

    function loadNode(node, resolve) {
      if (node.level === 0) {
        return resolve([
          {
            label: 'region',
            value: 'region',
            isLeaf: true,
          },
        ])
      }
      if (node.level > 2) return resolve([])

      setTimeout(() => {
        const data = [
          {
            label: 'leaf-' + node.level,
            value: 'leaf-' + node.level,
            isLeaf: node.level <= 2,
          },
          {
            label: 'zone-' + node.level,
            value: 'zone-' + node.level,
          },
        ]
        resolve(data)
      }, 500)
    }

    return {
      select,
      data,
      loadNode,
    }
  },
})
</script>
显示代码

配置

参数说明类型可选值默认值
v-model绑定值string / array--
data绑定数据array--
config配置绑定数据键值object-{ value: ‘value’, label: ‘label’, disabled: ‘disabled’, children: ‘children’ }
multiple是否多选boolean-false
disabled是否禁用boolean-false
size尺寸stringlarge / default /small-
clearable是否可以清空选项boolean-false
collapse-tags多选时是否将选中值按文字的形式展示boolean-false
collapse-tags-tooltip当鼠标悬停折叠标签的文本时是否显示所有选定的标签。 当 collapse-tagstrue 生效boolean-false
nameselect input 的 name 属性string--
autocompleteselect input 的 autocomplete 属性stringon / offoff
placeholder占位符string-请选择
only-select-leaf是否只选取子节点boolean-false
filterable是否可过滤树形boolean-false
reserve-keyword多选且可过滤时,是否在选中一个选项后保留当前的搜索关键词boolean-false
teleported是否将 Select 的下拉菜单 teleport 至 bodyboolean-true
automatic-dropdown对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单boolean-false
clear-icon自定义清空图标的类名string / Component-CircleClose
fit-input-width下拉框的宽度是否与输入框相同booleanfalse
suffix-icon自定义后缀图标组件string / ComponentArrowUp
tag-type标签类型stringsuccess / info / warning / dangerinfo
render-after-expand是否在第一次展开某个树节点后才渲染其子节点boolean-true
load加载子树数据的方法,仅当 lazy 属性为 true 时生效function(node, resolve)--
render-content树节点的内容区的渲染 FunctionFunction(h, { node, data, store }--
default-expand-all是否默认展开所有节点boolean-false
expand-on-click-node是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。boolean-true
check-on-click-node是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。boolean-false
auto-expand-parent展开子节点的时候是否自动展开父节点boolean-true
check-strictly在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 falseboolean-false
filter-node-method对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏Function(value, data, node)--
accordion是否每次只打开一个同级树节点展开boolean-false
indent相邻级节点间的水平缩进,单位为像素number-16
icon-class自定义树节点的图标string--
lazy是否懒加载子节点,需与 load 方法结合使用boolean-false
draggable是否开启拖拽节点功能boolean-false
allow-drag判断节点能否被拖拽Function(node)--
allow-drop拖拽时判定目标节点能否被放置。type 参数有三种情况:‘prev’、‘inner’ 和 ‘next’,分别表示放置在目标节点前、插入至目标节点和放置在目标节点后Function(draggingNode, dropNode, type)--

事件

名称说明回调参数
change选中值发生变化时触发目前的选中值
visible-change下拉框出现/隐藏时触发出现则为 true,隐藏则为 false
remove-tag多选模式下移除 tag 时触发移除的 tag 值
clear可清空的单选模式下用户点击清空按钮时触发-
blur当 input 失去焦点时触发(event: Event)
focus当 input 获得焦点时触发(event: Event)
node-click节点被点击时的回调共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。
node-contextmenu当某一节点被鼠标右键点击时会触发该事件共四个参数,依次为:event、传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。
check-change节点选中状态发生变化时的回调共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点
check当复选框被点击的时候触发共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
current-change当前选中节点变化时触发的事件共两个参数,依次为:当前节点的数据,当前节点的 Node 对象
node-expand节点被展开时触发的事件共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
node-collapse节点被关闭时触发的事件共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
node-drag-start节点开始拖拽时触发的事件共两个参数,依次为:被拖拽节点对应的 Node、event
node-drag-enter拖拽进入其他节点时触发的事件共三个参数,依次为:被拖拽节点对应的 Node、所进入节点对应的 Node、event
node-drag-leave拖拽离开某个节点时触发的事件共三个参数,依次为:被拖拽节点对应的 Node、所离开节点对应的 Node、event
node-drag-over在拖拽节点时触发的事件(类似浏览器的 mouseover 事件)共三个参数,依次为:被拖拽节点对应的 Node、当前进入节点对应的 Node、event
node-drag-end拖拽结束时(可能未成功)触发的事件共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点(可能为空)、被拖拽节点的放置位置(before、after、inner)、event
node-drop拖拽成功完成时触发的事件共四个参数,依次为:被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置(before、after、inner)、event

插槽

名称说明
-自定义树节点的内容,参数为 { node, item, multiple }