Tree V2 虚拟化树形控件beta

不论你的数据量多大,虚拟树都能毫无压力地处理。

基础用法

基础的树形结构展示

Virtualized Tree 虚拟化树形控件 - 图1

  1. <template>
  2. <el-tree-v2 :data="data" :props="props" :height="208" />
  3. </template>
  4. <script lang="ts" setup>
  5. interface Tree {
  6. id: string
  7. label: string
  8. children?: Tree[]
  9. }
  10. const getKey = (prefix: string, id: number) => {
  11. return `${prefix}-${id}`
  12. }
  13. const createData = (
  14. maxDeep: number,
  15. maxChildren: number,
  16. minNodesNumber: number,
  17. deep = 1,
  18. key = 'node'
  19. ): Tree[] => {
  20. let id = 0
  21. return Array.from({ length: minNodesNumber })
  22. .fill(deep)
  23. .map(() => {
  24. const childrenNumber =
  25. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  26. const nodeKey = getKey(key, ++id)
  27. return {
  28. id: nodeKey,
  29. label: nodeKey,
  30. children: childrenNumber
  31. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  32. : undefined,
  33. }
  34. })
  35. }
  36. const props = {
  37. value: 'id',
  38. label: 'label',
  39. children: 'children',
  40. }
  41. const data = createData(4, 30, 40)
  42. </script>

可选择的虚拟树

适用于需要选择层级时使用。

Virtualized Tree 虚拟化树形控件 - 图2

  1. <template>
  2. <el-tree-v2 :data="data" :props="props" show-checkbox :height="208" />
  3. </template>
  4. <script lang="ts" setup>
  5. interface Tree {
  6. id: string
  7. label: string
  8. children?: Tree[]
  9. }
  10. const getKey = (prefix: string, id: number) => {
  11. return `${prefix}-${id}`
  12. }
  13. const createData = (
  14. maxDeep: number,
  15. maxChildren: number,
  16. minNodesNumber: number,
  17. deep = 1,
  18. key = 'node'
  19. ): Tree[] => {
  20. let id = 0
  21. return Array.from({ length: minNodesNumber })
  22. .fill(deep)
  23. .map(() => {
  24. const childrenNumber =
  25. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  26. const nodeKey = getKey(key, ++id)
  27. return {
  28. id: nodeKey,
  29. label: nodeKey,
  30. children: childrenNumber
  31. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  32. : undefined,
  33. }
  34. })
  35. }
  36. const props = {
  37. value: 'id',
  38. label: 'label',
  39. children: 'children',
  40. }
  41. const data = createData(4, 30, 40)
  42. </script>

禁用复选框

节点的复选框可以设置为禁用。

在示例中,属性在 defaultProps 中声明了 disabled,一些节点被设置为 disable:true。 相应的复选框已禁用,不能点击。

Virtualized Tree 虚拟化树形控件 - 图3

  1. <template>
  2. <el-tree-v2 :data="data" :props="props" show-checkbox :height="208" />
  3. </template>
  4. <script lang="ts" setup>
  5. interface Tree {
  6. id: string
  7. label: string
  8. children?: Tree[]
  9. }
  10. const getKey = (prefix: string, id: number) => {
  11. return `${prefix}-${id}`
  12. }
  13. const createData = (
  14. maxDeep: number,
  15. maxChildren: number,
  16. minNodesNumber: number,
  17. deep = 1,
  18. key = 'node'
  19. ): Tree[] => {
  20. let id = 0
  21. return Array.from({ length: minNodesNumber })
  22. .fill(deep)
  23. .map(() => {
  24. const childrenNumber =
  25. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  26. const nodeKey = getKey(key, ++id)
  27. return {
  28. id: nodeKey,
  29. label: nodeKey,
  30. children: childrenNumber
  31. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  32. : undefined,
  33. }
  34. })
  35. }
  36. const props = {
  37. value: 'id',
  38. label: 'label',
  39. children: 'children',
  40. disabled: 'disabled',
  41. }
  42. const data = createData(4, 30, 40)
  43. </script>

默认扩展和默认检查

树节点可以在初始化阶段被设置为展开或选中。

分别通过 default-expanded-keysdefault-checked-keys 设置默认展开和默认选中的节点。

Virtualized Tree 虚拟化树形控件 - 图4

  1. <template>
  2. <el-tree-v2
  3. :data="data"
  4. :height="208"
  5. :props="props"
  6. show-checkbox
  7. :default-checked-keys="defaultCheckedKeys"
  8. :default-expanded-keys="defaultExpandedKeys"
  9. />
  10. </template>
  11. <script lang="ts" setup>
  12. import { ref } from 'vue'
  13. interface Tree {
  14. id: string
  15. label: string
  16. children?: Tree[]
  17. }
  18. const getKey = (prefix: string, id: number) => {
  19. return `${prefix}-${id}`
  20. }
  21. const createData = (
  22. maxDeep: number,
  23. maxChildren: number,
  24. minNodesNumber: number,
  25. deep = 1,
  26. key = 'node'
  27. ): Tree[] => {
  28. let id = 0
  29. return Array.from({ length: minNodesNumber })
  30. .fill(deep)
  31. .map(() => {
  32. const childrenNumber =
  33. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  34. const nodeKey = getKey(key, ++id)
  35. return {
  36. id: nodeKey,
  37. label: nodeKey,
  38. children: childrenNumber
  39. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  40. : undefined,
  41. }
  42. })
  43. }
  44. const props = {
  45. value: 'id',
  46. label: 'label',
  47. children: 'children',
  48. }
  49. const data = createData(4, 30, 40)
  50. const checkedKeys: string[] = []
  51. const expanedKeys: string[] = []
  52. for (const datum of data) {
  53. const children = datum.children
  54. if (children) {
  55. expanedKeys.push(datum.id)
  56. checkedKeys.push(children[0].id)
  57. break
  58. }
  59. }
  60. const defaultCheckedKeys = ref(checkedKeys)
  61. const defaultExpandedKeys = ref(expanedKeys)
  62. </script>

自定义节点内容

节点的内容支持自定义,可以在节点区添加按钮或图标等内容

Virtualized Tree 虚拟化树形控件 - 图5

  1. <template>
  2. <el-tree-v2 :data="data" :props="props" :height="208">
  3. <template #default="{ node }">
  4. <span class="prefix" :class="{ 'is-leaf': node.isLeaf }"
  5. >[ElementPlus]</span
  6. >
  7. <span>{{ node.label }}</span>
  8. </template>
  9. </el-tree-v2>
  10. </template>
  11. <script lang="ts" setup>
  12. interface Tree {
  13. id: string
  14. label: string
  15. children?: Tree[]
  16. }
  17. const getKey = (prefix: string, id: number) => {
  18. return `${prefix}-${id}`
  19. }
  20. const createData = (
  21. maxDeep: number,
  22. maxChildren: number,
  23. minNodesNumber: number,
  24. deep = 1,
  25. key = 'node'
  26. ): Tree[] => {
  27. let id = 0
  28. return Array.from({ length: minNodesNumber })
  29. .fill(deep)
  30. .map(() => {
  31. const childrenNumber =
  32. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  33. const nodeKey = getKey(key, ++id)
  34. return {
  35. id: nodeKey,
  36. label: nodeKey,
  37. children: childrenNumber
  38. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  39. : undefined,
  40. }
  41. })
  42. }
  43. const props = {
  44. value: 'id',
  45. label: 'label',
  46. children: 'children',
  47. }
  48. const data = createData(4, 30, 40)
  49. </script>
  50. <style scoped>
  51. .prefix {
  52. color: var(--el-color-primary);
  53. margin-right: 10px;
  54. }
  55. .prefix.is-leaf {
  56. color: var(--el-color-success);
  57. }
  58. </style>

节点过滤

树节点可以过滤

在需要对节点进行过滤时,调用 Tree 实例的 filter 方法, 参数为关键字。 需要注意的是,此时需要设置 filter-method,值为过滤函数。

Virtualized Tree 虚拟化树形控件 - 图6

  1. <template>
  2. <el-input
  3. v-model="query"
  4. placeholder="Please enter keyword"
  5. @input="onQueryChanged"
  6. />
  7. <el-tree-v2
  8. ref="treeRef"
  9. :data="data"
  10. :props="props"
  11. :filter-method="filterMethod"
  12. :height="208"
  13. />
  14. </template>
  15. <script lang="ts" setup>
  16. import { ref } from 'vue'
  17. import { ElTreeV2 } from 'element-plus'
  18. import type { TreeNode } from 'element-plus/es/components/tree-v2/src/types'
  19. interface Tree {
  20. id: string
  21. label: string
  22. children?: Tree[]
  23. }
  24. const getKey = (prefix: string, id: number) => {
  25. return `${prefix}-${id}`
  26. }
  27. const createData = (
  28. maxDeep: number,
  29. maxChildren: number,
  30. minNodesNumber: number,
  31. deep = 1,
  32. key = 'node'
  33. ): Tree[] => {
  34. let id = 0
  35. return Array.from({ length: minNodesNumber })
  36. .fill(deep)
  37. .map(() => {
  38. const childrenNumber =
  39. deep === maxDeep ? 0 : Math.round(Math.random() * maxChildren)
  40. const nodeKey = getKey(key, ++id)
  41. return {
  42. id: nodeKey,
  43. label: nodeKey,
  44. children: childrenNumber
  45. ? createData(maxDeep, maxChildren, childrenNumber, deep + 1, nodeKey)
  46. : undefined,
  47. }
  48. })
  49. }
  50. const query = ref('')
  51. const treeRef = ref<InstanceType<typeof ElTreeV2>>()
  52. const data = createData(4, 30, 5)
  53. const props = {
  54. value: 'id',
  55. label: 'label',
  56. children: 'children',
  57. }
  58. const onQueryChanged = (query: string) => {
  59. // TODO: fix typing when refactor tree-v2
  60. // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  61. // @ts-expect-error
  62. treeRef.value!.filter(query)
  63. }
  64. const filterMethod = (query: string, node: TreeNode) => {
  65. return node.label!.includes(query)
  66. }
  67. </script>

TreeV2 属性

属性说明类型默认值
data展示数据array
empty-text内容为空的时候展示的文本string
props配置选项,具体看下表object
highlight-current是否高亮当前选中节点booleanfalse
expand-on-click-node是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点booleantrue
check-on-click-node是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点booleanfalse
default-expanded-keys默认展开的节点的 key 的数组array
show-checkbox节点是否可被选择booleanfalse
check-strictly在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 falsebooleanfalse
default-checked-keys默认勾选的节点的 key 的数组array
current-node-key当前选中的节点string, number
filter-method对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示, 返回 false 则表示这个节点会被隐藏Function(value, data)
indent相邻级节点间的水平缩进,单位为像素number16
icon自定义树节点的图标string | Component-

props

属性说明类型默认值
value每个树节点用来作为唯一标识的属性,在整棵树中应该是唯一的string, numberid
label指定节点标签为节点对象的某个属性值stringlabel
children指定子树为节点对象的某个属性值stringchildren
disabled指定节点选择框是否禁用为节点对象的某个属性值stringdisabled

TreeV2 方法

Tree内部使用TreeNode类型的对象来包装用户传入的数据,用来构造树节点之间的关系。 Tree 暴露了以下方法:

方法说明参数
filter对树节点进行筛选操作(query: string)
getCheckedNodes若节点可被选择(即show-checkboxtrue),则返回目前被选中的节点所组成的数组(leafOnly: boolean)
getCheckedKeys若节点可被选择(即 show-checkboxtrue),则返回目前被选中的节点的 key 所组成的数组(leafOnly: boolean)
setCheckedKeys通过 keys 设置目前勾选的节点(keys: TreeKey[])
setChecked通过 key 设置某个节点的勾选状态(key: TreeKey, checked: boolean)
setExpandedKeys设置当前展开的节点(keys: TreeKey[])
getHalfCheckedNodes如果节点可用被选中 (show-checkboxtrue), 它将返回当前半选中的节点组成的数组-
getHalfCheckedKeys若节点可被选中(show-checkboxtrue),则返回目前半选中的节点的 key 所组成的数组-
getCurrentKey获取当前被选中节点的 key,若没有节点被选中则返回 undefined-
getCurrentNode获取当前被选中节点的 data,若没有节点被选中则返回 undefined-
setCurrentKey通过 key 设置某个节点的当前选中状态(key: TreeKey)
getNode通过 key 或 data 获取节点(data: TreeKey | TreeNodeData)
expandNode展开指定节点(node: TreeNode)
collapseNode折叠指定节点(node: TreeNode)
setData当数据量非常庞大的时候,总是使用响应式数据将导致性能表现不佳,所以我们提供一种显式设置的方式来避免此种情况(data: TreeData)

TreeV2 事件

事件名说明参数
node-click当节点被点击的时候触发(data: TreeNodeData, node: TreeNode, e: MouseEvent)
node-contextmenu当节点被鼠标右键点击时会触发该事件(e: Event, data: TreeNodeData, node: TreeNode)
check-change节点选中状态发生变化时的回调(data: TreeNodeData, checked: boolean)
check当复选框被点击的时候触发(data: TreeNodeData, info: { checkedKeys: TreeKey[],checkedNodes: TreeData, halfCheckedKeys: TreeKey[], halfCheckedNodes: TreeData,})
current-change当前选中节点变化时触发的事件(data: TreeNodeData, node: TreeNode)
node-expand节点被展开时触发的事件(data: TreeNodeData, node: TreeNode)
node-collapse节点被收起时触发的事件(data: TreeNodeData, node: TreeNode)

TreeV2 插槽

名称说明
-自定义树节点的内容。 作用域参数为 { node: TreeNode, data: TreeNodeData }

源代码

组件 Virtualized Tree 虚拟化树形控件 - 图7 文档 Virtualized Tree 虚拟化树形控件 - 图8

贡献者

Virtualized Tree 虚拟化树形控件 - 图9 三咲智子

Virtualized Tree 虚拟化树形控件 - 图10 zz

Virtualized Tree 虚拟化树形控件 - 图11 msidolphin

Virtualized Tree 虚拟化树形控件 - 图12 jeremywu

Virtualized Tree 虚拟化树形控件 - 图13 bqy_fe

Virtualized Tree 虚拟化树形控件 - 图14 C.Y.Kun

Virtualized Tree 虚拟化树形控件 - 图15 秦皇岛

Virtualized Tree 虚拟化树形控件 - 图16 webfansplz

Virtualized Tree 虚拟化树形控件 - 图17 Zhongxiang Wang

Virtualized Tree 虚拟化树形控件 - 图18 opengraphica

Virtualized Tree 虚拟化树形控件 - 图19 Jobin

Virtualized Tree 虚拟化树形控件 - 图20 Delyan Haralanov

Virtualized Tree 虚拟化树形控件 - 图21 Aex

Virtualized Tree 虚拟化树形控件 - 图22 btea

Virtualized Tree 虚拟化树形控件 - 图23 renovate[bot]

Virtualized Tree 虚拟化树形控件 - 图24 qiang

Virtualized Tree 虚拟化树形控件 - 图25 Chen_Z