• 树形控件
    • 何时使用
    • 代码演示
      • 受控操作示例
      • 基本用法
      • 自定义图标
      • 拖动示例
      • 异步数据加载
      • 连接线
      • 可搜索
      • 目录
  • API
    • Tree props
    • 事件
    • TreeNode props
    • DirectoryTree props

    树形控件

    何时使用

    文件夹、组织架构、生物分类、国家地区等等,世间万物的大多数结构都是树形结构。使用树控件可以完整展现其中的层级关系,并具有展开收起选择等交互功能。

    代码演示

    Tree树形控件 - 图1

    受控操作示例

    受控操作示例

    1. <template>
    2. <a-tree
    3. checkable
    4. @expand="onExpand"
    5. :expandedKeys="expandedKeys"
    6. :autoExpandParent="autoExpandParent"
    7. v-model="checkedKeys"
    8. @select="onSelect"
    9. :selectedKeys="selectedKeys"
    10. :treeData="treeData"
    11. />
    12. </template>
    13. <script>
    14. const treeData = [{
    15. title: '0-0',
    16. key: '0-0',
    17. children: [{
    18. title: '0-0-0',
    19. key: '0-0-0',
    20. children: [
    21. { title: '0-0-0-0', key: '0-0-0-0' },
    22. { title: '0-0-0-1', key: '0-0-0-1' },
    23. { title: '0-0-0-2', key: '0-0-0-2' },
    24. ],
    25. }, {
    26. title: '0-0-1',
    27. key: '0-0-1',
    28. children: [
    29. { title: '0-0-1-0', key: '0-0-1-0' },
    30. { title: '0-0-1-1', key: '0-0-1-1' },
    31. { title: '0-0-1-2', key: '0-0-1-2' },
    32. ],
    33. }, {
    34. title: '0-0-2',
    35. key: '0-0-2',
    36. }],
    37. }, {
    38. title: '0-1',
    39. key: '0-1',
    40. children: [
    41. { title: '0-1-0-0', key: '0-1-0-0' },
    42. { title: '0-1-0-1', key: '0-1-0-1' },
    43. { title: '0-1-0-2', key: '0-1-0-2' },
    44. ],
    45. }, {
    46. title: '0-2',
    47. key: '0-2',
    48. }]
    49. export default {
    50. data () {
    51. return {
    52. expandedKeys: ['0-0-0', '0-0-1'],
    53. autoExpandParent: true,
    54. checkedKeys: ['0-0-0'],
    55. selectedKeys: [],
    56. treeData,
    57. }
    58. },
    59. watch: {
    60. checkedKeys(val) {
    61. console.log('onCheck', val)
    62. }
    63. },
    64. methods: {
    65. onExpand (expandedKeys) {
    66. console.log('onExpand', expandedKeys)
    67. // if not set autoExpandParent to false, if children expanded, parent can not collapse.
    68. // or, you can remove all expanded children keys.
    69. this.expandedKeys = expandedKeys
    70. this.autoExpandParent = false
    71. },
    72. onCheck (checkedKeys) {
    73. console.log('onCheck', checkedKeys)
    74. this.checkedKeys = checkedKeys
    75. },
    76. onSelect (selectedKeys, info) {
    77. console.log('onSelect', info)
    78. this.selectedKeys = selectedKeys
    79. },
    80. },
    81. }
    82. </script>

    Tree树形控件 - 图2

    基本用法

    最简单的用法,展示可勾选,可选中,禁用,默认展开等功能。

    1. <template>
    2. <a-tree
    3. checkable
    4. :treeData="treeData"
    5. :defaultExpandedKeys="['0-0-0', '0-0-1']"
    6. :defaultSelectedKeys="['0-0-0', '0-0-1']"
    7. :defaultCheckedKeys="['0-0-0', '0-0-1']"
    8. @select="this.onSelect"
    9. @check="this.onCheck"
    10. >
    11. <span slot="title0010" style="color: #1890ff">sss</span>
    12. </a-tree>
    13. </template>
    14. <script>
    15. const treeData = [{
    16. title: 'parent 1',
    17. key: '0-0',
    18. children: [{
    19. title: 'parent 1-0',
    20. key: '0-0-0',
    21. disabled: true,
    22. children: [
    23. { title: 'leaf', key: '0-0-0-0', disableCheckbox: true },
    24. { title: 'leaf', key: '0-0-0-1' },
    25. ],
    26. }, {
    27. title: 'parent 1-1',
    28. key: '0-0-1',
    29. children: [
    30. { key: '0-0-1-0', slots: { title: 'title0010' }},
    31. ],
    32. }],
    33. }]
    34. export default {
    35. data () {
    36. return {
    37. treeData,
    38. }
    39. },
    40. methods: {
    41. onSelect (selectedKeys, info) {
    42. console.log('selected', selectedKeys, info)
    43. },
    44. onCheck (checkedKeys, info) {
    45. console.log('onCheck', checkedKeys, info)
    46. },
    47. },
    48. }
    49. </script>

    Tree树形控件 - 图3

    自定义图标

    可以针对不同的节点定制图标。

    1. <template>
    2. <a-tree
    3. :treeData="treeData"
    4. showIcon
    5. defaultExpandAll
    6. :defaultSelectedKeys="['0-0-0']"
    7. >
    8. <a-icon slot="smile" type="smile-o" />
    9. <a-icon slot="meh" type="smile-o" />
    10. <template slot="custom" slot-scope="{selected}">
    11. <a-icon :type="selected ? 'frown':'frown-o'" />
    12. </template>
    13. </a-tree>
    14. </template>
    15. <script>
    16. const treeData = [{
    17. title: 'parent 1',
    18. key: '0-0',
    19. slots: {
    20. icon: 'smile',
    21. },
    22. children: [
    23. { title: 'leaf', key: '0-0-0', slots: { icon: 'meh' }},
    24. { title: 'leaf', key: '0-0-1', scopedSlots: { icon: 'custom' }}],
    25. }]
    26. export default {
    27. data () {
    28. return {
    29. treeData,
    30. }
    31. },
    32. methods: {
    33. onSelect (selectedKeys, info) {
    34. console.log('selected', selectedKeys, info)
    35. },
    36. onCheck (checkedKeys, info) {
    37. console.log('onCheck', checkedKeys, info)
    38. },
    39. },
    40. }
    41. </script>

    Tree树形控件 - 图4

    拖动示例

    将节点拖拽到其他节点内部或前后。

    1. <template>
    2. <a-tree
    3. class="draggable-tree"
    4. :defaultExpandedKeys="expandedKeys"
    5. draggable
    6. @dragenter="onDragEnter"
    7. @drop="onDrop"
    8. :treeData="gData"
    9. />
    10. </template>
    11. <script>
    12. const x = 3
    13. const y = 2
    14. const z = 1
    15. const gData = []
    16. const generateData = (_level, _preKey, _tns) => {
    17. const preKey = _preKey || '0'
    18. const tns = _tns || gData
    19. const children = []
    20. for (let i = 0; i < x; i++) {
    21. const key = `${preKey}-${i}`
    22. tns.push({ title: key, key })
    23. if (i < y) {
    24. children.push(key)
    25. }
    26. }
    27. if (_level < 0) {
    28. return tns
    29. }
    30. const level = _level - 1
    31. children.forEach((key, index) => {
    32. tns[index].children = []
    33. return generateData(level, key, tns[index].children)
    34. })
    35. }
    36. generateData(z)
    37. export default {
    38. data () {
    39. return {
    40. gData,
    41. expandedKeys: ['0-0', '0-0-0', '0-0-0-0'],
    42. }
    43. },
    44. methods: {
    45. onDragEnter (info) {
    46. console.log(info)
    47. // expandedKeys 需要受控时设置
    48. // this.expandedKeys = info.expandedKeys
    49. },
    50. onDrop (info) {
    51. console.log(info)
    52. const dropKey = info.node.eventKey
    53. const dragKey = info.dragNode.eventKey
    54. const dropPos = info.node.pos.split('-')
    55. const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
    56. const loop = (data, key, callback) => {
    57. data.forEach((item, index, arr) => {
    58. if (item.key === key) {
    59. return callback(item, index, arr)
    60. }
    61. if (item.children) {
    62. return loop(item.children, key, callback)
    63. }
    64. })
    65. }
    66. const data = [...this.gData]
    67. // Find dragObject
    68. let dragObj
    69. loop(data, dragKey, (item, index, arr) => {
    70. arr.splice(index, 1)
    71. dragObj = item
    72. })
    73. if (!info.dropToGap) {
    74. // Drop on the content
    75. loop(data, dropKey, (item) => {
    76. item.children = item.children || [];
    77. // where to insert 示例添加到尾部,可以是随意位置
    78. item.children.push(dragObj);
    79. });
    80. } else if (
    81. (info.node.children || []).length > 0 // Has children
    82. && info.node.expanded // Is expanded
    83. && dropPosition === 1 // On the bottom gap
    84. ) {
    85. loop(data, dropKey, (item) => {
    86. item.children = item.children || [];
    87. // where to insert 示例添加到尾部,可以是随意位置
    88. item.children.unshift(dragObj);
    89. });
    90. } else {
    91. let ar;
    92. let i;
    93. loop(data, dropKey, (item, index, arr) => {
    94. ar = arr;
    95. i = index;
    96. });
    97. if (dropPosition === -1) {
    98. ar.splice(i, 0, dragObj);
    99. } else {
    100. ar.splice(i + 1, 0, dragObj);
    101. }
    102. }
    103. this.gData = data
    104. },
    105. },
    106. }
    107. </script>

    Tree树形控件 - 图5

    异步数据加载

    点击展开节点,动态加载数据。

    1. <template>
    2. <a-tree
    3. :loadData="onLoadData"
    4. :treeData="treeData"
    5. />
    6. </template>
    7. <script>
    8. export default {
    9. data () {
    10. return {
    11. treeData: [
    12. { title: 'Expand to load', key: '0' },
    13. { title: 'Expand to load', key: '1' },
    14. { title: 'Tree Node', key: '2', isLeaf: true },
    15. ],
    16. }
    17. },
    18. methods: {
    19. onLoadData (treeNode) {
    20. return new Promise((resolve) => {
    21. if (treeNode.dataRef.children) {
    22. resolve()
    23. return
    24. }
    25. setTimeout(() => {
    26. treeNode.dataRef.children = [
    27. { title: 'Child Node', key: `${treeNode.eventKey}-0` },
    28. { title: 'Child Node', key: `${treeNode.eventKey}-1` },
    29. ]
    30. this.treeData = [...this.treeData]
    31. resolve()
    32. }, 1000)
    33. })
    34. },
    35. },
    36. }
    37. </script>

    Tree树形控件 - 图6

    连接线

    带连接线的树。

    1. <template>
    2. <a-tree
    3. showLine
    4. :defaultExpandedKeys="['0-0-0']"
    5. @select="onSelect"
    6. >
    7. <a-tree-node key="0-0">
    8. <span slot="title" style="color: #1890ff">parent 1</span>
    9. <a-tree-node title="parent 1-0" key="0-0-0">
    10. <a-tree-node title="leaf" key="0-0-0-0" />
    11. <a-tree-node title="leaf" key="0-0-0-1" />
    12. <a-tree-node title="leaf" key="0-0-0-2" />
    13. </a-tree-node>
    14. <a-tree-node title="parent 1-1" key="0-0-1">
    15. <a-tree-node title="leaf" key="0-0-1-0" />
    16. </a-tree-node>
    17. <a-tree-node title="parent 1-2" key="0-0-2">
    18. <a-tree-node title="leaf" key="0-0-2-0" />
    19. <a-tree-node title="leaf" key="0-0-2-1" />
    20. </a-tree-node>
    21. </a-tree-node>
    22. </a-tree>
    23. </template>
    24. <script>
    25. export default {
    26. methods: {
    27. onSelect (selectedKeys, info) {
    28. console.log('selected', selectedKeys, info)
    29. },
    30. },
    31. }
    32. </script>

    Tree树形控件 - 图7

    可搜索

    可搜索的树。

    1. <template>
    2. <div>
    3. <a-input-search style="margin-bottom: 8px" placeholder="Search" @change="onChange" />
    4. <a-tree
    5. @expand="onExpand"
    6. :expandedKeys="expandedKeys"
    7. :autoExpandParent="autoExpandParent"
    8. :treeData="gData"
    9. >
    10. <template slot="title" slot-scope="{title}">
    11. <span v-if="title.indexOf(searchValue) > -1">
    12. {{title.substr(0, title.indexOf(searchValue))}}
    13. <span style="color: #f50">{{searchValue}}</span>
    14. {{title.substr(title.indexOf(searchValue) + searchValue.length)}}
    15. </span>
    16. <span v-else>{{title}}</span>
    17. </template>
    18. </a-tree>
    19. </div>
    20. </template>
    21. <script>
    22. const x = 3
    23. const y = 2
    24. const z = 1
    25. const gData = []
    26. const generateData = (_level, _preKey, _tns) => {
    27. const preKey = _preKey || '0'
    28. const tns = _tns || gData
    29. const children = []
    30. for (let i = 0; i < x; i++) {
    31. const key = `${preKey}-${i}`
    32. tns.push({ title: key, key, scopedSlots: { title: 'title' }})
    33. if (i < y) {
    34. children.push(key)
    35. }
    36. }
    37. if (_level < 0) {
    38. return tns
    39. }
    40. const level = _level - 1
    41. children.forEach((key, index) => {
    42. tns[index].children = []
    43. return generateData(level, key, tns[index].children)
    44. })
    45. }
    46. generateData(z)
    47. const dataList = []
    48. const generateList = (data) => {
    49. for (let i = 0; i < data.length; i++) {
    50. const node = data[i]
    51. const key = node.key
    52. dataList.push({ key, title: key })
    53. if (node.children) {
    54. generateList(node.children, node.key)
    55. }
    56. }
    57. }
    58. generateList(gData)
    59. const getParentKey = (key, tree) => {
    60. let parentKey
    61. for (let i = 0; i < tree.length; i++) {
    62. const node = tree[i]
    63. if (node.children) {
    64. if (node.children.some(item => item.key === key)) {
    65. parentKey = node.key
    66. } else if (getParentKey(key, node.children)) {
    67. parentKey = getParentKey(key, node.children)
    68. }
    69. }
    70. }
    71. return parentKey
    72. }
    73. export default {
    74. data () {
    75. return {
    76. expandedKeys: [],
    77. searchValue: '',
    78. autoExpandParent: true,
    79. gData,
    80. }
    81. },
    82. methods: {
    83. onExpand (expandedKeys) {
    84. this.expandedKeys = expandedKeys
    85. this.autoExpandParent = false
    86. },
    87. onChange (e) {
    88. const value = e.target.value
    89. const expandedKeys = dataList.map((item) => {
    90. if (item.key.indexOf(value) > -1) {
    91. return getParentKey(item.key, gData)
    92. }
    93. return null
    94. }).filter((item, i, self) => item && self.indexOf(item) === i)
    95. Object.assign(this, {
    96. expandedKeys,
    97. searchValue: value,
    98. autoExpandParent: true,
    99. })
    100. },
    101. },
    102. }
    103. </script>

    Tree树形控件 - 图8

    目录

    内置的目录树,multiple 模式支持 ctrl(Windows) / command(Mac) 复选。

    1. <template>
    2. <a-directory-tree
    3. multiple
    4. defaultExpandAll
    5. @select="onSelect"
    6. @expand="onExpand"
    7. >
    8. <a-tree-node title="parent 0" key="0-0">
    9. <a-tree-node title="leaf 0-0" key="0-0-0" isLeaf />
    10. <a-tree-node title="leaf 0-1" key="0-0-1" isLeaf />
    11. </a-tree-node>
    12. <a-tree-node title="parent 1" key="0-1">
    13. <a-tree-node title="leaf 1-0" key="0-1-0" isLeaf />
    14. <a-tree-node title="leaf 1-1" key="0-1-1" isLeaf />
    15. </a-tree-node>
    16. </a-directory-tree>
    17. </template>
    18. <script>
    19. export default {
    20. methods: {
    21. onSelect (keys) {
    22. console.log('Trigger Select', keys);
    23. },
    24. onExpand () {
    25. console.log('Trigger Expand');
    26. },
    27. },
    28. }
    29. </script>

    API

    Tree props

    参数说明类型默认值
    treeData节点的配置描述,具体项见下表, 1.1.4之前的版本使用treeNodesarray
    autoExpandParent是否自动展开父节点booleantrue
    checkable节点前添加 Checkbox 复选框booleanfalse
    checkedKeys(v-model)(受控)选中复选框的树节点(注意:父子节点有关联,如果传入父节点key,则子节点自动选中;相应当子节点key都传入,父节点也自动选中。当设置checkablecheckStrictly,它是一个有checkedhalfChecked属性的对象,并且父子节点的选中与否不再关联string[] | number[] | {checked: string[] | number[], halfChecked: string[] | number[]}[]
    checkStrictlycheckable状态下节点选择完全受控(父子节点选中状态不再关联)booleanfalse
    defaultCheckedKeys默认选中复选框的树节点string[] | number[][]
    defaultExpandAll默认展开所有树节点booleanfalse
    defaultExpandedKeys默认展开指定的树节点string[] | number[][]
    defaultExpandParent默认展开父节点booltrue
    defaultSelectedKeys默认选中的树节点string[] | number[][]
    disabled将树禁用boolfalse
    draggable设置节点可拖拽booleanfalse
    expandedKeys(.sync)(受控)展开指定的树节点string[] | number[][]
    filterTreeNode按需筛选树节点(高亮),返回truefunction(node)-
    loadData异步加载数据function(node)-
    loadedKeys(受控)已经加载的节点,需要配合 loadData 使用string[] | number[][]
    multiple支持点选多个节点(节点本身)booleanfalse
    selectedKeys(.sync)(受控)设置选中的树节点string[] | number[]-
    showIcon是否展示 TreeNode title 前的图标,没有默认样式,如设置为 true,需要自行定义图标相关样式booleanfalse
    showLine是否展示连接线booleanfalse

    事件

    事件名称说明回调参数
    check点击复选框触发function(checkedKeys, e:{checked: bool, checkedNodes, node, event})
    dragenddragend 触发时调用function({event, node})
    dragenterdragenter 触发时调用function({event, node, expandedKeys})
    dragleavedragleave 触发时调用function({event, node})
    dragoverdragover 触发时调用function({event, node})
    dragstart开始拖拽时调用function({event, node})
    dropdrop 触发时调用function({event, node, dragNode, dragNodesKeys})
    expand展开/收起节点时触发function(expandedKeys, {expanded: bool, node})
    load节点加载完毕时触发function(loadedKeys, {event, node})
    rightClick响应右键点击function({event, node})
    select点击树节点触发function(selectedKeys, e:{selected: bool, selectedNodes, node, event})

    TreeNode props

    结点描述数据对象,是 treeNodes 中的一项,TreeNode 使用相同的 API。

    参数说明类型默认值
    class节点的 classstring-
    style节点的 stylestring|object-
    disableCheckbox禁掉 checkboxbooleanfalse
    disabled禁掉响应booleanfalse
    icon自定义图标。可接收组件,props 为当前节点 propsslot|slot-scope-
    isLeaf设置为叶子节点(设置了loadData时有效)booleanfalse
    key被树的 (default)ExpandedKeys / (default)CheckedKeys / (default)SelectedKeys 属性所用。注意:整个树范围内的所有节点的 key 值不能重复!string | number内部计算出的节点位置
    selectable设置节点是否可被选中booleantrue
    title标题string|slot|slot-scope'—-'
    slots使用treeNodes时,可以通过该属性配置支持slot的属性,如 slots: { title: 'XXX'}object-
    scopedSlots使用columns时,可以通过该属性配置支持slot-scope的属性,如 scopedSlots: { title: 'XXX'}object-
    on事件对象,仅在treeNodes使用方式中生效,如{click: () => {}}object'—-'

    DirectoryTree props

    参数说明类型默认值
    expandAction目录展开逻辑,可选 false 'click' 'doubleclick'stringclick