再帰は、アルゴリズムで学ぶのが常に苦痛でした。 ただし、場合によっては、再帰を使用する方が反復を使用するよりも自然に感じることがあります。 ツリーをトラバースすることもその1つです。

同じ仕組みに従うことで、Vue.jsやその他のフレームワークで再帰的なコンポーネントを作成できます。

ツリーコンポーネントの作成

たとえば、ディレクトリツリーを表示するなど、ツリー構造をレンダリングする必要があるコンポーネントを想像してみてください。

+ Root directory
  + Directory A
    + Directory A1
  + Directory B

ディレクトリをツリーとして表し、すべてのサブディレクトリをそのツリーのノードのリストとして表すことができます。 ツリーには常にルートノードがあり、リーフノードに到達するまで拡張されます。

たとえば、次のようなオブジェクトを使用できます labelchildren そのための鍵:

const tree = {
  label: "A cool folder",
  children: [
    {
      label: "A cool sub-folder 1",
      children: [
        { label: "A cool sub-sub-folder 1" },
        { label: "A cool sub-sub-folder 2" }
      ]
    },
    { label: "This one is not that cool" }
  ]
}

前の構造を前提として、それを小道具として受け取り、ルートノードをレンダリングするTree.vueコンポーネントを作成しましょう。

Tree.vue
<template>
  <div class="tree">
    <ul class="tree-list">
      <node-tree :node="treeData"></node-tree>
    </ul>
  </div>
</template>

<script>
import NodeTree from "./NodeTree";

export default {
  props: {
    treeData: Object
  },
  components: {
    NodeTree
  }
};
</script>

<style>
.tree-list ul {
  padding-left: 16px;
  margin: 6px 0;
}
</style>

リストの左側にいくつかのパディングを追加しているので、リストはその階層的な外観になっています。

ここでは特別なことは何も起こっていません。 treeData プロパティを取得し、それを最初のノードとして、まだ実装していないNodeTreeコンポーネントに渡します。

ノードツリーの実装

ノードツリーはそのラベルを表示する必要がありますが、同時にその子をレンダリングする必要があります。 このように、NodeTreeはサブツリーでもあります。

単純なNodeTree.vueコンポーネントは次のようになります。

NodeTree.vue
<template>
  <li class="node-tree">
    <span class="label">{{ node.label }}</span>
  </li>
</template>

<script>
export default {
  props: {
    node: Object
  }
};
</script>

ただし、コンポーネントはラベルを表示するだけであり、ツリーノードでもある子をレンダリングするようにする必要があります。

考えてみれば、再帰関数と同じです。 これらは、条件が満たされない限り、自分自身を呼び出す関数です。

したがって、ノードツリーにノードツリーのリストをレンダリングさせる必要があります。 同じコンポーネントからコンポーネントにアクセスするには、を追加する必要があります name コンポーネントオプション:

NodeTree.vue
<template>
  <li class="node-tree">
    <span class="label">{{ node.label }}</span>

    <ul v-if="node.children && node.children.length">
      <node v-for="child in node.children" :node="child"></node>
    </ul>
  </li>
</template>

<script>
export default {
  name: "node",
  props: {
    node: Object
  }
};
</script>

これにより、 NodeTree コンポーネントは、リーフノードに到達するまでそれ自体を呼び出します。

ご覧のとおり、使用しています name: "node" したがって、 <node> 鬼ごっこ。 子ツリーノードは、子が存在する場合にのみレンダリングされ、子ノードをプロパティとして渡します。

ツリーコンポーネントの使用

たとえば、試してみるために、 App.vue コンポーネントを作成して、前のデータ構造をTreeコンポーネントに渡すことができます。

App.vue
<template>
  <div>
    <tree :tree-data="tree"></tree>
  </div>
</template>

<script>
import Tree from "./Tree";

export default {
  data: () => ({
    tree: {
      label: "A cool folder",
      children: [
        {
          label: "A cool sub-folder 1",
          children: [
            { label: "A cool sub-sub-folder 1" },
            { label: "A cool sub-sub-folder 2" }
          ]
        },
        { label: "This one is not that cool" }
      ]
    }
  }),
  components: {
    Tree
  }
};
</script>

まとめ

再帰は難しいものである必要はありません。Vue.jsはDSLまたはテンプレートからのサポートを提供することで簡単に再帰を作成できます。

この記事が素晴らしいツリーコンポーネントの構築に役立つことを願っています!

涼しくしてください🦄