递归组件是可以在它们⾃⼰模板中调⽤⾃身的组件。
    例如,下⾯是Node.vue

    1. <template>
    2. <div>
    3. <h3>{{ data.name }}</h3>
    4. <!-- 有条件嵌套 -->
    5. <Node v-for="n in data.children" :key="n.name" :data="n"> </Node>
    6. </div>
    7. </template>
    8. <script>
    9. export default {
    10. name: "Node", // name对递归组件是必要的
    11. props: {
    12. data: {
    13. type: Object,
    14. require: true,
    15. },
    16. },
    17. };
    18. </script>

    递归组件的数据通常是⼀棵树,NodeTest.vue

    1. <template>
    2. <div>
    3. <Node :data="folder"></Node>
    4. </div>
    5. </template>
    6. <script>
    7. import Node from "@/components/recursion/Node.vue";
    8. export default {
    9. components: {
    10. Node,
    11. },
    12. data() {
    13. return {
    14. // 树形结构的数据
    15. folder: {
    16. name: "vue-study",
    17. children: [
    18. { name: "src", children: [{ name: "main.js" }] },
    19. { name: "package.json" },
    20. ],
    21. },
    22. };
    23. },
    24. };
    25. </script>

    适当添加⼀些缩进

    1. <h3 :style="{'text-indent': indent+'em'}">{{data.name}}</h3>
    1. export default {
    2. props: {
    3. // 添加⼀个层级属性
    4. level: {
    5. type: Number,
    6. default: 0,
    7. },
    8. },
    9. computed: {
    10. indent() {
    11. // 缩进两个字的宽度
    12. return this.level * 2;
    13. },
    14. },
    15. };

    实现Tree组件
    Tree组件是典型的递归组件,其他的诸如菜单组件都属于这⼀类,也是相当常⻅的。
    实现tree-node组件,recursion/TreeNode.vue

    1. <template>
    2. <div>
    3. <div @click="toggle" :style="{paddingLeft: (level-1)+'em'}">
    4. <label>{{model.title}}</label>
    5. <span v-if="isFolder">[{{open ? '-' : '+'}}]</span>
    6. </div>
    7. <div v-show="open" v-if="isFolder">
    8. <tree-node class="item" v-for="model in model.children"
    9. :model="model" :key="model.title"
    10. :level="level + 1"></tree-node>
    11. </div>
    12. </div>
    13. </template>
    14. <script>
    15. export default {
    16. name: "tree-node",
    17. props: {
    18. model: Object,
    19. level: {
    20. type: Number,
    21. default: 1
    22. }
    23. },
    24. data: function() {
    25. return {
    26. open: false
    27. };
    28. },
    29. computed: {
    30. isFolder: function() {
    31. return this.model.children && this.model.children.length;
    32. }
    33. },
    34. methods: {
    35. toggle: function() {
    36. if (this.isFolder) {
    37. this.open = !this.open;
    38. }
    39. },
    40. }
    41. };
    42. </script>

    实现tree组件,recursion/Tree.vue

    1. <template>
    2. <div class="kkb-tree">
    3. <TreeNode v-for="item in data" :key="item.title" :model="item"></TreeNode>
    4. </div>
    5. </template>
    6. <script>
    7. import TreeNode from "@/components/recursion/TreeNode.vue";
    8. export default {
    9. props: {
    10. data: {
    11. type: Array,
    12. required: true,
    13. },
    14. },
    15. components: {
    16. TreeNode,
    17. },
    18. };
    19. </script>
    20. <style scoped>
    21. .kkb-tree {
    22. text-align: left;
    23. }
    24. </style>

    使用,recursion/index.vue

    1. <template>
    2. <Tree :data="treeData"></Tree>
    3. </template>
    4. <script>
    5. import Tree from "@/components/recursion/Tree.vue";
    6. export default {
    7. data() {
    8. return {
    9. treeData: [
    10. {
    11. title: "Web全栈架构师",
    12. children: [
    13. {
    14. title: "Java架构师",
    15. },
    16. {
    17. title: "JS高级",
    18. children: [
    19. {
    20. title: "ES6",
    21. },
    22. {
    23. title: "动效",
    24. },
    25. ],
    26. },
    27. {
    28. title: "Web全栈",
    29. children: [
    30. {
    31. title: "Vue训练营",
    32. expand: true,
    33. children: [
    34. {
    35. title: "组件化",
    36. },
    37. {
    38. title: "源码",
    39. },
    40. {
    41. title: "docker部署",
    42. },
    43. ],
    44. },
    45. {
    46. title: "React",
    47. children: [
    48. {
    49. title: "JSX",
    50. },
    51. {
    52. title: "虚拟DOM",
    53. },
    54. ],
    55. },
    56. {
    57. title: "Node",
    58. },
    59. ],
    60. },
    61. ],
    62. },
    63. ],
    64. };
    65. },
    66. components: {
    67. Tree,
    68. },
    69. };
    70. </script>