コンポーネントの構成

学習の目的

この単元を完了すると、次のことができるようになります。
  • コンポーネントを構成する。
  • スロットを使用する。
  • 2 つのプログラミングモデルのデータバインドの動作の違いを挙げる。

コンポーネントは別のコンポーネントのボディに追加できます。コンポーネントのこうした構成によって、シンプルなビルディングブロックコンポーネントから複雑なコンポーネントを構築できます。

大きなアプリケーションの場合は、コードの再利用性とメンテナンス性を高めるため、一連の小さなコンポーネントを使用してアプリケーションを作成すると便利です。

lightning 名前空間には、コンポーネントの構築に使用できる lightning-button などの基本コンポーネントが多数含まれています。詳細は、コンポーネントライブラリを参照してください。

コンポーネントのリレーションの理解

まずは、単純な例を見ながら、構成コンポーネントに関する用語をいくつか定義しましょう。この説明は、不必要な脱線のように思えるかもしれませんが、他の開発者と話すときに一貫した用語を使用するのは重要なことです。

<!-- owner.html -->
<template>
    <c-child first-name="Moonbeam"></c-child>
<template>

この HTML ファイルでは <c-child> が使用されています。これは c 名前空間にある child コンポーネントを参照します。組織の名前空間プレフィックスを設定していない場合、作成したコンポーネントを参照するときにはデフォルトの c 名前空間を使用します。

所有者: 所有者は、テンプレートを所有するコンポーネントです。この例では、所有者は c-owner コンポーネントです。所有者は、含まれているすべての構成コンポーネントを制御します。所有者は次のことができます。
  • 構成コンポーネントの公開プロパティを設定する。
  • 構成コンポーネントで公開メソッドをコールする。
  • 構成コンポーネントによって起動されるイベントをリスンする。
親と子: あるコンポーネントに別のコンポーネントが含まれている (同様にこれにも他のコンポーネントを含むことができる) 場合、コンテインメント階層があります。ドキュメント内で親コンポーネントと子コンポーネントに言及することがあります。親コンポーネントには子コンポーネントが含まれます。親コンポーネントは、所有者の場合もあれば、所有者のテンプレートの一部でもあるコンテナコンポーネントの場合もあります。次の例では、c-parent-container は c-child が含まれているので、コンテナコンポーネントです。c-parent-container コンポーネントは、c-owner 所有者コンポーネントのテンプレート内にあるので所有者ではありません。
<!-- owner.html -->
<template>
    <c-parent-container>
        <c-child first-name="Moonbeam"></c-child>
    </c-parent-container>
<template>

DreamHouse の例

コンポーネントの構成の例を見てみましょう。PropertyTileList Aura コンポーネントには、PropertyTile コンポーネントが含まれています。

<aura:component>
    ...
    <div class="slds-card">
        <lightning:layout horizontalAlign="center" multipleRows="true">
            <aura:iteration items="{!v.properties}" var="property">
                <lightning:layoutItem padding="around-small" size="12" smallDeviceSize="6" mediumDeviceSize="4" largeDeviceSize="3">
                    <c:PropertyTile property="{#property}"/>
                </lightning:layoutItem>    
            </aura:iteration>
        </lightning:layout>
    </div>
</aura:component>

PropertyTile コンポーネントには、property と呼ばれる属性があります。その名前に気を取られないでください。DreamHouse は不動産アプリケーションなので、ここで言っているのは、JavaScript のプロパティではなく不動産物件のことです。

以下は、propertyTileList Lightning Web コンポーネントの HTML です。

<template>
    <div class="slds-card tile-list">
        <template for:each={filteredProperties} for:item="property">
            <c-property-tile property={property} key={property.Id}></c-property-tile>
        </template>
    </div>
</template>

マークアップは、構成コンポーネントを参照する構文を除けば、2 つのプログラミングモデルで類似しています。Aura モデルと Lightning Web コンポーネントモデルでは、マークアップでコンポーネントを参照する構文がどのように異なるかについてすでに説明しました。

  • Aura コンポーネントでは、c:PropertyTile を使用します。
  • Lightning Web コンポーネントでは、c-property-tile を使用します。c 名前空間とコンポーネント名はダッシュで区切られます。キャメルケースの propertyTile Lightning Web コンポーネントは、それを含む別の Lightning Web コンポーネントの HTML ファイルでは property-tile として参照されます。

Lightning Web コンポーネントに Lightning Web コンポーネントが含まれる

lwcContainerComponent と lwcComponent という 2 つの Lightning Web コンポーネントによる構成を見てみましょう。

<!-- lwcContainerComponent.html -->
<template>
    <c-lwc-component></c-lwc-component>
</template>

lwcComponent Lightning Web コンポーネントを別の Lightning Web コンポーネントで使用する方法は次のとおりです。

  • c 名前空間とコンポーネント名をダッシュで区切ります。
  • キャメルケースの名前 lwcComponent を lwc-component というケバブケース (ダッシュ区切り) の参照に変更します。Web コンポーネント標準と一貫性を保つため、ダッシュ区切りの参照を使用します。
  • HTML 仕様では、カスタム要素のタグは自己終了でないことが規定されています。自己終了タグは /> で終わります。Lightning Web コンポーネントは、基本的にはカスタム要素です。したがって、コンポーネントの参照には開始タグと終了タグが必要です。
    <c-lwc-component></c-lwc-component>

Aura コンポーネントに Lightning Web コンポーネントが含まれる

lwcContainerComponent という Lightning Web コンポーネントを含む auraWrapper という Aura コンポーネントを見てみましょう。

<!-- auraWrapper.cmp -->
<aura:component>
    <c:lwcContainerComponent />
</aura:component>

lwcContainerComponent Lightning Web コンポーネントを Aura コンポーネントで使用する方法は次のとおりです。

  • c 名前空間とコンポーネント名をコロンで区切ります。
  • キャメルケースのコンポートメント名 lwcContainerComponent を使用します。
  • Aura マークアップでは自己終了タグが許されているので、<c:lwcContainerComponent /> を使用します。

ファセットはスロットになる

Aura では、ファセットは Aura.Component[] 型の任意の属性です。属性にコンポーネントの配列を設定できるということを専門用語で言うとそうなります。さらに簡単に言うならば、ファセットをサンドイッチのようなものと考えてください。サンドイッチ (ファセット) には、何種類もの具 (コンポーネント) を好きなだけ挟むことができます。

たとえば、すべての Aura コンポーネントは body 属性を継承します。これはファセットです。ファセットの概念が重要なのは、親コンポーネントが設定できるマークアップのプレースホルダであるコンポーネント属性を、設計することができるからです。

Lightning Web コンポーネントでは、ファセットの代わりにスロットを使用します。スロットは、親コンポーネントがコンポーネントの body に渡すマークアップのプレースホルダです。HTML の <slot> 要素は、Web コンポーネント標準の一部です。

以下は、すべてのコンポーネントでデフォルトで使用される header ファセットと body ファセットを含む Aura コンポーネントの例です。

<aura:component>
    <aura:attribute name="header" type="Aura.Component[]"/>
    <div>
        <span>{!v.header}</span><br/>
        <span>{!v.body}</span>
    </div>
</aura:component>

同様の Lightning Web コンポーネントは次のようになります。

<template>
    <div>
        <slot name="header"></slot><br/>
        <slot></slot>
    </div>
</template>

header ファセットは、header という名前のスロットに置き換わります。body ファセットは、名前のないスロットに置き換わります。

詳細は、『Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド)』を参照してください。

ファセットに関するその他の考慮事項は?

よくぞ聞いてくれました。Lightning Web コンポーネントに Aura コンポーネントを含めることはできません。ファセットを含む Aura コンポーネントを移行する場合、ファセットに含めるサブコンポーネントもすべて移行する必要があります。そうすることで、Aura コンポーネントが Lightning Web コンポーネントに含まれることがないようにします。

データバインドの違い

マークアップにコンポーネントを追加すると、所有者コンポーネントのプロパティ値に基づいて子コンポーンネントの公開プロパティ値を初期化できます。データバインドの動作は、2 つのプログラミングモデルで異なります。

Aura コンポーネントのデータバインド

Aura コンポーネントでは、データバインドの式構文として {!expr} と {#expr} という 2 つの形式を使用できます。これらの違いについてはここで説明しませんが、簡単な例を見てみましょう。

<!-- owner.cmp -->
<aura:component>
    <aura:attribute name="fName" type="String" />
    <c:child firstName="{!v.fName}"/>
</aura:component>

所有者コンポーネントは fName 属性の値を子コンポーネントに渡します。その結果が 2 つのコンポーネントのデータバインド (値バインド) です。

Aura コンポーネントでは、このデータバインドは双方向になります。fName 属性の変更は子コンポーネントの firstName 属性に渡され、子コンポーネントの firstName 属性の値は所有者コンポーネントの fName 属性に返されます。この 2 方向データバインドは、パフォーマンスに対してコストが高くなる場合があり、特に深くネストされたコンポーネントがあると、データ変更の伝達に起因するデバッグが難しいエラーを引き起こす可能性があります。

Lightning Web コンポーネントのデータバインド

Lightning Web コンポーネントでは、プロパティ値のデータバインドは一方向になります。所有者コンポーネントでプロパティ値が変更されると、更新された値が子コンポーネントに伝達されます。その逆は起こりません

簡単なデータバインドの例を見てみましょう。

<!-- owner.html -->
<template>
    <c-child first-name={fName}></child>
</template>

データバインドの動作は、Lightning Web コンポーネントでは意図的により単純で予測可能になっています。子コンポーネントは、所有者コンポーネントから渡されたプロパティ値を読み取り専用として扱う必要があります。子コンポーネントが所有者コンポーネントから渡された値を変更すると、ブラウザコンソールにエラーが表示されます。

所有者コンポーネントが提供するプロパティ値の変異をトリガするために、子コンポーネントは親にイベントを送信できます。親がデータを所有している場合、親はプロパティ値を変更でき、これは一方向データバインドで子コンポーネントに伝達されます。

リソース