マークアップと CSS の移行
学習の目的
- Aura コンポーネントから Lightning Web コンポーネントへ HTML とマークアップを移行する。
- Aura コンポーネントから Lightning Web コンポーネントへ CSS を移行する。
DreamHouse アプリケーション
Aura コンポーネントと Lightning Web コンポーネントのプログラミングモデルを比較する最善の方法は、2 つのモデルで記述された類似のコンポーネントのコードを見てみることです。
Lightning コンポーネントを紹介するために Salesforce が開発した DreamHouse アプリケーションという比較的複雑なアプリケーションの一部であるコンポーネントをいくつか見てみます。DreamHouse は Salesforce プラットフォーム上に構築された不動産業向けのサンプルアプリケーションです。このアプリケーションを使って、仲介担当者は物件を管理し、買主は念願のマイホームを見つけることができます。
DreamHouse アプリケーションは、Aura コンポーネントが実装されたものと、Lightning Web コンポーネントが実装されたものがあり、それぞれの完全なコードは 2 つの異なる GitHub リポジトリにあります。アプリケーションの両バージョンの機能は同じではありませんが、2 つのプログラミングモデルを比較する上で有用なコンポーネントがいくつかあります。
DreamHouse アプリケーションの 2 つの実装のコードは GitHub リポジトリにあります。
Aura コンポーネントのコードスニペットを参照し、Aura コードが Lightning Web コンポーネントコードにどのようにマッピングされるか説明します。また、Aura コンポーネントの概念が Lightning Web コンポーネントではどのように変換されるのかについても説明します。コアスニペットを中心にこれらの概念を説明します。その後、他のコンテキストに興味がある場合は、コンポーネントを調べることができます。
コンポーネントのバンドル
Aura コンポーネントと Lightning Web コンポーネントでは、コンポーネントバンドルのファイル構造が異なります。2 種類のコンポーネント間でファイルは次のようにマッピングされます。
リソース | Aura のファイル | Lightning Web コンポーネントのファイル |
---|---|---|
マークアップ | sample.cmp | sample.html |
管理者 | sampleController.js | sample.js |
ヘルパー | sampleHelper.js | |
レンダラー | sampleRenderer.js | |
CSS | sample.css | sample.css |
ドキュメント | sample.auradoc | 現在利用できません。 |
設計 | sample.design | sample.js-meta.xml |
SVG | sample.svg | HTML ファイルに含めるか、静的リソースとしてアップロードします。 |
Lightning Web コンポーネントには HTML ファイル、JavaScript ファイル、設定ファイルを含める必要があります。省略可能な CSS ファイルと追加の JavaScript ファイルを含めることができます。
サービスコンポーネントまたはライブラリとも呼ばれる、UI を表示しないコンポーネントには、JavaScript ファイルとメタデータ設定ファイルを含める必要があります。
この単元では、HTML ファイルと CSS ファイルを見ていきます。次の単元では、JavaScript ファイルについて説明します。
Lightning Web コンポーネントにはさらに設定ファイルがあります。このファイルは、Lightning アプリケーションビルダー向けのコンポーネントのデザイン設定を含め、コンポーネントのメタデータ値を定義します。Aura コンポーネントでは、設定ファイルにはインターフェースによって定義されるメタデータ (flexipage:availableForRecordHome など) が保存されています。
マークアップの移行
Aura コンポーネントでは、マークアップは .cmp ファイルに保存されています。このファイルは <aura:component> タグで始まり、HTML および Aura 固有のタグを含めることができます。
Lightning Web コンポーネントでは、マークアップは .html ファイルに保存されています。このファイルは <template> タグで始まり、動的コンテンツの HTML とディレクティブを含めることができます。
Aura のマークアップが Lightning Web コンポーネントの HTML ファイルと JavaScript ファイルの内容にどのようにマッピングされるのか見てみましょう。
属性は JavaScript プロパティになる
Aura コンポーネントのマークアップ (.cmp) の <aura:attribute> タグの属性を、Lightning Web コンポーネントの JavaScript ファイル (.js) の JavaScript プロパティに移行します。
PropertySummary Aura コンポーネントのマークアップでこれらの属性を見てみましょう。完全なファイルは DreamHouse Aura コンポーネントの GitHub リポジトリにあります。
<aura:attribute name="recordId" type="Id" /> <aura:attribute name="property" type="Property__c" />
Lightning Web コンポーネントでは、マークアップの属性の代わりに JavaScript プロパティを使用します。propertySummary.js でプロパティを見てみましょう。
import { LightningElement, api } from 'lwc'; export default class PropertySummary extends LightningElement { @api recordId; property; ... }
Aura コンポーネントの recordId および property 属性は、Lightning Web コンポーネントの recordId および property JavaScript プロパティになります。
@api デコレーターは recordId を公開プロパティとしてマークします。公開プロパティはコンポーネントの公開 API の一部です。つまり、Lightning アプリケーションビルダー、またはマークアップでコンポーネントを使用する親コンポーネントで設定することができます。
Aura の基本的な式は HTML の式になる
Aura コンポーネントのマークアップの基本的な式を、Lightning Web コンポーネントの HTML の式に移行します。基本的な式の例として、Aura コンポーネントの属性の参照があります。
たとえば、PropertyPaginator Aura コンポーネントでは、基本的な式を使用して page、pages、total 属性の値を表示します。
<aura:component > <aura:attribute name="page" type="integer"/> <aura:attribute name="pages" type="integer"/> <aura:attribute name="total" type="integer"/> <div class="centered">{!v.total} properties • page {!v.page} of {!v.pages}</div> </aura:component>
以下は、paginator Lightning Web コンポーネントの HTML ファイルの同等の構文です。
<template> {totalItemCount} items • page {currentPageNumber} of {totalPages} </template>
HTML は paginator.js の totalItemCount プロパティを参照します。{currentPageNumber} および {totalPages} 式は、pageNumber および pageSize プロパティを処理する getter を参照します。
import { LightningElement, api } from 'lwc'; export default class Paginator extends LightningElement { /** The current page number. */ @api pageNumber; /** The number of items on a page. */ @api pageSize; /** The total number of items in the list. */ @api totalItemCount; get currentPageNumber() { return this.totalItemCount === 0 ? 0 : this.pageNumber; } get totalPages() { return Math.ceil(this.totalItemCount / this.pageSize); } }
条件付きステートメントを理解したらすぐに、より複雑な式に取り組みます。
Aura の条件式は HTML の条件式になる
Aura コンポーネントの <aura:if> タグを、Lightning Web コンポーネントの HTML ファイルの lwc:if、lwc:elseif、または lwc:else ディレクティブに移行します。
以下に、BrokerDetails Aura コンポーネントの条件付きマークアップを示します。
<aura:if isTrue="{!v.property.Broker__c}"> <lightning:recordForm recordId="{!v.property.Broker__c}" objectApiName="Broker__c" fields="{!v.brokerFields}" columns="2"/> </aura:if>
以下は、brokerCard Lightning Web コンポーネントの同様の HTML です。
<template lwc:if={property.data}> <lightning-record-form object-api-name="Broker__c" record-id={brokerId} fields={brokerFields} columns="2"> </lightning-record-form> </template>
Lightning Web コンポーネントの HTML ファイルは <template> 標準 HTML タグで始まり、そのボディ内に他の <template> タグを含めることもできます。この例では、<template> タグ内のコンテンツは、lwc:if ディレクティブの結果に応じて条件付きで表示されます。
Aura の複合式は JavaScript ロジックになる
属性値の参照など、Aura の基本的な式は HTML 式になることを確認しました。Aura コンポーネントの Aura 複合式 (比較演算や 3 項演算子など) を Lightning Web コンポーネントの JavaScript getter に移行します。
PropertyPaginator Aura コンポーネントで {!v.page > 1} が使用されているこの例のように、Aura コンポーネントでは豊富な式がサポートされています。
<aura:if isTrue="{!v.page > 1}"> <lightning:buttonIcon iconName="utility:left" variant="border" onclick="{!c.previousPage}"/> </aura:if>
Aura の式言語では、マークアップにより多くのロジックを含めることができます。その欠点は、このロジックの単体テストを行うことが難しくなり、唯一 JavaScript で単体テストができるコードのサブセットは機能です。
Lightning Web コンポーネントでは、複合式を JavaScript に移行します。これでコードを単体テストできるようになり、コードがより安定し、開発者は満足します。また、JavaScript のフル機能を使用してロジックを記述できます。
以下は、paginator Lightning Web コンポーネントの同様の HTML です。
<template lwc:if={isNotFirstPage}> <lightning-button-icon icon-name="utility:chevronleft" onclick={previousHandler}></lightning-button-icon> </template>
paginator.js の getter によって {isNotFirstPage} 条件が評価されます。次に例を示します。
import { LightningElement, api } from 'lwc'; export default class Paginator extends LightningElement { /** The current page number. */ @api pageNumber; get isNotFirstPage() { return this.pageNumber > 1; } }
Aura のイテレーションは HTML のイテレーションになる
Aura コンポーネントの <aura:iteration> タグを、Lightning Web コンポーネントの HTML ファイルの for:each ディレクティブに移行します。
以下は、PropertyTileList.cmp の Aura 構文です。
<aura:iteration items="{!v.properties}" var="property"> <c:PropertyTile property="{#property}"/> </aura:iteration>
以下は、propertyTileList Lightning Web コンポーネントの同様の HTML です。
<template for:each={properties.data.records} for:item="property"> <c-property-tile property={property} key={property.Id} onselected={handlePropertySelected}></c-property-tile> </template>
Aura の初期化子はライフサイクルフックになる
Aura コンポーネントの init イベントハンドラーを、Lightning Web コンポーネントの connectedCallback() JavaScript メソッドに置き換えます。connectedCallback() ライフサイクルフックは、コンポーネントが DOM に挿入されたときに起動します。ライフサイクルフックは、コンポーネントのライフサイクルの各フェーズでコードを実行できるコールバックメソッドです。
Aura コンポーネントでは init イベント使用して、コンポーネント構築後、表示する前にコンポーネントを初期化します。
以下は、PropertyCarousel Aura コンポーネントの init イベントハンドラーです。
<aura:handler name="init" value="{!this}" action="{!c.onInit}" />
Aura コンポーネントのコントローラーの onInit 関数で、必要な初期化が実行されます。
Lightning Web コンポーネントでは、コンポーネントの JavaScript ファイルの代わりに connectedCallback() を使用します。以下に、propertySummary.js の例を示します。
export default class PropertySummary extends LightningElement { ... connectedCallback() { // initialize component } }
基本コンポーネントの移行
Lightning Web コンポーネントに Aura コンポーネントを含めることはできません。では、移行する必要がある Aura コンポーネントに Salesforce が提供する組み込みコンポーネントが含まれている場合は、どうしたらよいのでしょうか。Lightning 基本コンポーネントは Salesforce が lightning 名前空間で提供するビルディングブロックであり、Aura コンポーネントと Lightning Web コンポーネントの両方で使用できます。Lightning 基本コンポーネントを 2 つのプログラミングモデルで使用する場合、それぞれの構文は異なります。
この Aura コンポーネントでは、lightning:formattedNumber 基本コンポーネントが使用されています。
<aura:component> <lightning:formattedNumber value="5000" style="currency" currencyCode="USD" /> </aura:component>
このマークアップを Lightning Web コンポーネントに移行する方法は、次のとおりです。
- 名前空間 (lightning) とコンポーネント名 (formattedNumber) を区切るコロンをダッシュに変更します。
- キャメルケースのコンポーネント名 (formattedNumber) をダッシュで区切った名前 (formatted-number) に変更します。
- キャメルケースの属性名 (currencyCode) をダッシュで区切った名前 (currency-code) に変更します。
以下は、同等の Lightning Web コンポーネントです。
<template> <lightning-formatted-number value="5000" style="currency" currency-code="USD"> </lightning-formatted-number> </template>
Aura の CSS は標準 CSS になる
Lightning Web コンポーネントでは標準の CSS 構文が使用されます。Aura コンポーネントのみで使用される THIS クラスを削除します。
以下は、PropertyTile Aura コンポーネントの CSS ファイルの一部です。
.THIS .lower-third { position: absolute; bottom: 0; left: 0; right: 0; color: #FFF; background-color: rgba(0, 0, 0, .3); padding: 6px 8px; } .THIS .lower-third > p { padding: 0; margin: 0; } .THIS .truncate { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
propertyTile Lightning Web コンポーネントの同様の CSS では、標準の CSS が代わりに使用されます。THIS キーワードは Aura 固有のもので、Lightning Web コンポーネントでは使用されません。
.lower-third { position: absolute; bottom: 0; left: 0; right: 0; color: #FFF; background-color: rgba(0, 0, 0, .3); padding: 6px 8px; } .lower-third > p { padding: 0; margin: 0; } .truncate { width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
Lightning Design System を使用してコンポーネントのスタイルを設定する
Lightning Experience または Salesforce モバイルアプリケーションに存在するカスタムコンポーネントアプリケーションでは、import ステートメントや静的リソースなしで Lightning Design System を使用することができます。Lightning Design System の CSS クラスを HTML 要素に割り当てれば完了です。
Lightning Web コンポーネントは Aura コンポーネントのスタイル設定を継承する
Aura コンポーネントのスタイルは、含まれている Lightning Web コンポーネントに伝播します。
ただし、Lightning Web コンポーネントのスタイルが、他の Lightning Web コンポーネントや Aura コンポーネントに干渉することはありません。読み間違いではありません。Lightning Web コンポーネントのスタイルは子に伝播しません。多くの問題を引き起こす可能性があるので、自分が所有しないスタイルの上書きは Lightning Web コンポーネントでは許可されていません。
Shadow DOM を使用した CSS のカプセル化
Lightning Web コンポーネントでは、コンポーネントを含むページからコンポーネント内部の要素を非表示にする、shadow DOM と呼ばれる Web 標準メカニズムが使用されています。Lightning Web コンポーネントには shadow DOM があるので、コンポーネントのスタイルシートで定義されたスタイルはコンポーネントに範囲設定されます。これらのスタイルは、親、子、または兄弟コンポーネントには適用されません。このルールは厳格ですが、スタイルを失わずに異なるコンテキストでコンポーネントを再利用することができます。また、ページの他の部分のスタイルがコンポーネントのスタイルによって上書きされるのを防ぎます。
コンポーネント作成者が容易に開発できるようにするために、Lightning Web コンポーネントの shadow DOM は Web 標準とは少し異なる動作をします。その違いの 1 つは、Lightning Web コンポーネントの shadow DOM が自動的に作成されることです。コンポーネント作成者が実装する必要はありません。また、Lightning Web コンポーネントの shadow DOM は、shadow DOM をネイティブでサポートしないブラウザーでも機能します。
リソース
- Lightning Aura コンポーネント開発者ガイド: コンポーネントの作成
- Lightning Aura コンポーネント開発者ガイド: Lightning ページと Lightning アプリケーションビルダーのコンポーネントの設定
- Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド): Component Lifecycle Hooks (コンポーネントのライフサイクルフック)
- Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド): Component Configuration File (コンポーネント設定ファイル)