再帰コンポーネントの概要
再帰コンポーネントとは、テンプレート内で自身のコンポーネントを呼び出す仕組みを持つものです。ファイルシステムのようなツリー構造や、スレッド形式のコメント欄など、階層の深さが動的に変化するデータを描画する際に非常に有効なアプローチです。
nameオプションの役割
Vueにおいて再帰コンポーネントを動作させるためには、コンポーネントにnameオプションを付与することが不可欠です。テンプレート内で自身を参照する際、Vueがそのコンポーネントを正しく解決できるようにするためです。コンポーネントをグローバルに登録する場合も自己参照は可能ですが、単一ファイルコンポーネント等でローカルに定義する場合は明示的な名前の付与が必須となります。
<template>
<div class="container">
<!-- 自己参照による再帰呼び出し -->
<TreeBranch />
</div>
</template>
<script>
export default {
name: 'TreeBranch' // 自己参照の解決に必要
}
</script>
終了条件とイベント伝播
再帰処理を実装する上で最も注意すべき点は、無限ループによるスタックオーバーフローを防ぐための終了条件(ベースケース)の設定です。Propsで渡される階層の深さやデータの有無を条件に利用し、不要な再帰呼び出しを停止させる必要があります。
また、再帰コンポーネント間でイベントを親へ伝播させることも可能です。子コンポーネントで発生したカスタムイベントを$emitで捕捉し、さらにその親へとリレーすることで、最下層から最上位層へのイベント伝播を実現できます。
<template>
<div class="layer" @click="activate">
<!-- depthが1より大きい場合のみ子コンポーネントを描画 -->
<NestedLayer
v-if="depth > 1"
:depth="depth - 1"
@layer-activated="relaySignal"
/>
</div>
</template>
<script>
export default {
name: 'NestedLayer',
props: {
depth: {
type: Number,
required: true
}
},
methods: {
activate() {
// 現在の階層での処理を実行し、イベントを親へ伝播
this.relaySignal(this.depth);
},
relaySignal(currentDepth) {
// イベントを遅延させて親コンポーネントへバブリング
setTimeout(() => {
this.$emit('layer-activated', currentDepth - 1);
}, 100);
}
}
}
</script>