Vue递归组件的设计与实现

364 阅读1分钟

在vue中,组件是可以在它们自己的模板中调用自身的,这称为递归组件,比如Tree组件就是常见的递归组件。要设计一个递归组件,需满足两个条件:

  • 组件必须有name选项
  • 组件的递归调用有终止条件

根据这个思路,我们来看看如何设计一个Tree组件:

1、实现TreeItem

<!--TreeItem.vue-->
<template>
  <li class="tree-item-comp">
    <div class="tree-item-hd" @click="toggle">
      {{model.title}}
      <span class="toggle-icon" v-if="isFolder">[{{open? '-': '+'}}]</span>
    </div>
    <!-- 递归子Item -->
    <!-- 递归组件关键点二:递归有一个明确终止的条件 -->
    <ul v-if="isFolder" v-show="open">
        <tree-item v-for="model in model.children" 
            :model="model" 
            :key="model.title">
        </tree-item>
    </ul>
  </li>
</template>

<script>
export default {
  // 设计递归组件关键点一:必须有'name'选项
  name: "TreeItem",
  props: {
    model: {
      type: Object
    }
  },
  data() {
    return {
      open: false
    };
  },
  computed: {
    <!--如果this.model.children有值,说明它还有次级节点-->
    isFolder() {
      return this.model.children && this.model.children.length;
    }
  },
  methods: {
    toggle() {
      if (this.isFolder) {
        this.open = !this.open;
      }
    }
  }
};
</script>

2、实现Tree

<!--Tree.vue-->
<template>
  <div class="tree-comp">
    <ul>
      <tree-item :model="treeData"></tree-item>
    </ul>
  </div>
</template>


<script>
import TreeItem from "@/components/Tree/TreeItem";

export default {
  name: "Tree",
  components: {
    TreeItem
  },
  data() {
    return {
      treeData: {
        title: "Web全栈",
        children: [
          {
            title: "React"
          },
          {
            title: "Vue全家桶",
            children: [
              {
                title: "ElementUI"
              },
              {
                title: "Vue-Router"
              },
              {
                title: "Vuex"
              }
            ]
          },
          {
            title: "Node",
            children: [
              {
                title: "数据持久化",
                children: [
                  {
                    title: "mysql"
                  },
                  {
                    title: "mongodb"
                  },
                  {
                    title: "redis"
                  }
                ]
              },
              {
                title: "Node框架",
                children: [
                  {
                    title: "express"
                  },
                  {
                    title: "koa"
                  }
                ]
              },
              {
                title: "docker"
              }
            ]
          }
        ]
      }
    };
  }
};
</script>