跳到主要内容

递归组件

什么是递归组件

递归组件,顾名思义,就是自己的内部实现又调用自己的组件。 特点:

  • 组件必须设置 name 选项

递归组件的实现

Vue 官方实例 Tree-View

  • Home.vue

    :::details 点击查看代码

    <template>
    <div class="home">
    <Tree></Tree>
    </div>
    </template>

    <script>
    import Tree from "./Tree";
    export default {
    name: "Home",
    components: {
    Tree,
    },
    };
    </script>

    :::

  • Tree.vue

    :::details 点击查看代码

    <template>
    <ul class="Tree">
    <TreeItem
    class="TreeItem"
    :item="treeData"
    @make-folder="makeFolder"
    @add-item="addItem"
    ></TreeItem>
    </ul>
    </template>

    <script>
    import TreeItem from "./TreeItem";
    export default {
    name: "Tree",
    components: {
    TreeItem,
    },
    data() {
    return {
    treeData: {
    name: "世界您好!",
    children: [
    {
    name: "美国不好!",
    },
    {
    name: "英国不好!",
    },
    {
    name: "中国您好!",
    children: [
    {
    name: "北京好!",
    },
    {
    name: "杭州好!",
    },
    {
    name: "太原好!",
    },
    ],
    },
    ],
    },
    };
    },
    methods: {
    makeFolder(item) {
    this.$set(item, "children", []);
    this.addItem(item);
    },
    addItem(item) {
    console.log(item);
    if (!item.children) {
    this.$set(item, "children", []);
    }
    item.children.push({
    name: "新世界",
    });
    },
    },
    };
    </script>
    <style>
    .Tree {
    padding-left: 1em;
    line-height: 1.5em;
    list-style-type: dot;
    }
    .TreeItem {
    cursor: pointer;
    }
    .folder {
    font-weight: bold;
    }
    </style>

    :::

  • TreeItem.vue

    :::details 点击查看代码

    <template>
    <li>
    <div :class="{ folder: isFolder }" @click="toggle" @dblclick="makeFolder">
    {{ item.name }}
    <span v-if="isFolder">[{{ isOpen ? "-" : "+" }}]</span>
    </div>
    <ul v-show='isOpen' v-if='isFolder' class="Tree">
    <TreeItem
    class="TreeItem"
    v-for="(child, index) in item.children"
    :key="index"
    :item="child"
    @make-folder="$emit('make-folder', $event)"
    @add-item="$emit('add-item', $event)"
    ></TreeItem>
    <li class="add" @click="$emit('add-item', item)">+</li>
    </ul>
    </li>
    </template>

    <script>
    export default {
    name: "TreeItem",
    components: {},
    props: {
    item: {
    type: Object,
    },
    },
    data() {
    return {
    isOpen: false,
    };
    },
    computed: {
    isFolder() {
    return this.item.children && this.item.children.length;
    },
    },
    methods: {
    toggle() {
    if (this.isFolder) {
    this.isOpen = !this.isOpen;
    }
    },
    makeFolder() {
    if (!this.isFolder) {
    this.$emit("make-folder", this.item);
    this.isOpen = true;
    }
    },
    },
    };
    </script>

    :::