再帰的なコンポーネント

LWC(Lightning Web Component)で再帰的なコンポーネントを作成するには、コンポーネントが自身を呼び出す再帰的なパターンを設計する必要があります。再帰的なコンポーネントは、データ構造がツリー状にネストされている場合や、階層構造の要素を表示する場合に非常に便利です。以下は、LWCで再帰的なコンポーネントを作成する基本的なステップです。

  • 以下は再帰的なコンポーネントの例です
lwc
 ├─menu
 ├─menuItem
 └─menuContainer
  • menu
    image.png
<template>
    <div class="slds-dropdown-trigger slds-dropdown-trigger_click slds-is-open">
        <div class="slds-dropdown slds-dropdown_left slds-dropdown_small">
            <ul class="slds-dropdown__list">
                <c-menu-item child-items={_items}>
                </c-menu-item>
            </ul>
        </div>
    </div>
</template>
import { LightningElement, api } from 'lwc';

export default class Menu extends LightningElement {

    @api get items() {
        return this._items || [];
    }

    set items(value) {
        this._items = value;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
  • menuItem
    image.png
<template>
    <template for:each={_children} for:item="it" for:index="index">
        <template if:false={it.items}>
            <li class="slds-dropdown__item" role="presentation" key={item}>
                <a href="#">
                    <span class="slds-truncate" title={it.label}>{it.label}</span>
                </a>
            </li>
        </template>
        <template if:true={it.items}>
            <li class="slds-dropdown__header slds-truncate" key={item}>
                <span title={it.label}>{it.label}</span>
            </li>
            <c-menu-item child-items={it.items} key={item}></c-menu-item>
        </template>
    </template>
</template>
import { LightningElement, api, track } from 'lwc';

export default class MenuItem extends LightningElement {
    @track _children = [];

    /**
     * childItemsを取得
     */
    @api
    get childItems() {
        return this._children;
    }

    /**
     * childItemsを設定
     * @param {any} value
     */
    set childItems(value) {
        this._children = value || [];
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
  • menuContainer
    image.png
<template>
    <div class="slds-card" style="height:500px;width:1200px">
        <c-menu items={items}></c-menu>
    </div>
</template>
import { LightningElement, track } from 'lwc';

export default class MenuContainer extends LightningElement {

    @track items = [{
            label: 'メニュー1',
            items: [{
                label: 'サブメニュー1-1',
            }, {
                label: 'サブメニュー1-2',
            }, ],
        },
        {
            label: 'メニュー2',
            items: [{
                label: 'サブメニュー2-1',
            }, {
                label: 'サブメニュー2-2',
            }, ],
        },
    ];
}
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>52.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
  • ロカールで動作確認

menuContainer 中に右クリックし、SFDX:Preview Component Locallyを押下する
image.png

Use Desktop Browserを選択する
image.png

サーバを立ち上げて、ブラウザを自動的に開く
image.png

参考