Lightning Web コンポーネントの作成
学習の目的
この単元を完了すると、次のことができるようになります。
- 各コンポーネントファイルの内容を説明する。
- Lightning Web コンポーネントの JavaScript メソッドを作成する。
- コンポーネント JavaScript でライフサイクルフックを使用する。
実践してみよう
Salesforce の特定のオブジェクトとは関係なく、データ表示要素を作成するとします。ぴったりの例が、ebikes サンプルリポジトリにある productCard component です。そのカードコンポーネントを調べ、独自のバージョンをゼロから作成して、どうすればそれが本格的な Lightning Web コンポーネントに進化するのかを確認しましょう。コンポーネントの各部を構築し、他のサンプルを見て回ることで、すぐに基本を習得できます。
組織にステップアップ
この単元では、Salesforce 拡張機能を含む Visual Studio Code を使用して Lightning Web コンポーネントを開発します。
必要なもの
最初の単元で説明したように、続行するには Salesforce DX に習熟している必要があります。この単元を完了するには、次が必要です。
- Salesforce 拡張機能パックを含む Visual Studio Code (VS Code)
- Salesforce CLI
これらの要件を満たすには、「クイックスタート: Lightning Web コンポーネント」プロジェクトを修了してください。
HTML ファイルの中身
Lightning Web コンポーネントの HTML ファイルのすべてに、template
タグが含まれます。template
タグには、コンポーネントの構造を定義する HTML が含まれます。ebikes リポジトリにある productCard コンポーネントの簡易バージョンの HTML を見てみましょう。
以下の例を VS Code に貼り付けていきます。
- VS Code のコマンドパレットの [SFDX: Create Project (SFDX: プロジェクトを作成)] を選択してプロジェクトを作成します。標準テンプレートを受け入れ、
bikeCard
というプロジェクト名を付けます。
-
force-app/main/default で、lwc フォルダーを右クリックし、[SFDX: Create Lightning Web Component (SFDX: Lightning Web コンポーネントの作成)] を選択します。
- 新しいコンポーネントの名前に
app
と入力します。
-
Enter キーを押し、もう一度 Enter キーを押してデフォルトの
force-app/main/default/lwc
を受け入れます。
- 次のコードを app.html に貼り付けます (ファイル内の既存の HTML を置き換えます)。中括弧
<template> <div> <div>Name: {name}</div> <div>Description: {description}</div> <div>Category: {category}</div> <div>Material: {material}</div> <div>Price: {price}</div> <div><img src={pictureUrl} alt={name}/></div> </div> </template>
{}
で囲まれた識別子は、対応する JavaScript クラス内の同じ名前の項目にバインドされます。
- 次のコードを app.js に貼り付けます。
import { LightningElement } from 'lwc'; export default class App extends LightningElement { name = 'Electra X4'; description = 'A sweet bike built for comfort.'; category = 'Mountain'; material = 'Steel'; price = '$2,700'; pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'; }
- ファイルを保存します。
では、実例を使って試してみましょう。たとえば、データを表示するのに、読み込みに少し時間がかかることがわかっているとします。何かあったのかとユーザーを心配させたくありません。テンプレート内で lwc:if
および lwc:else
条件付きディレクティブを使用して、どの視覚要素が表示されているかを判別できます。
- 次のコードを app.html に貼り付けます。"display"
div
タグ内のコンテンツは、HTML ファイルのready
の値がtrue
になるまで表示されません。<template> <template lwc:if={ready}> <div id="display"> <div>Name: {name}</div> <div>Description: {description}</div> <div>Category: {category}</div> <div>Material: {material}</div> <div>Price: {price}</div> <div><img src={pictureUrl} alt={name}/></div> </div> </template> <template lwc:else> <div id="waiting">Loading…</div> </template> </template>
- 次のコードを app.js に貼り付けます。ここではデータ値が保持され、3 秒のタイマーが設定されます。3 秒後に、コンテンツは表示されるはずです。(もちろん、これはテストのみが目的です)。
import { LightningElement } from 'lwc'; export default class App extends LightningElement { name = 'Electra X4'; description = 'A sweet bike built for comfort.'; category = 'Mountain'; material = 'Steel'; price = '$2,700'; pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'; ready = false; connectedCallback() { setTimeout(() => { this.ready = true; }, 3000); } }
- ファイルを保存します。
基本 Lightning Web コンポーネント
すべてのコンポーネントをゼロから作成したくはないでしょう。そこで、基本 Lightning Web コンポーネントを使用することを検討します。当然、データ型、表示コントローラー、ナビゲーション項目など、多くのコンポーネントがあります。そのすべては、「Component Reference (コンポーネントリファレンス)」にリストされています。
自転車の詳細が目立つようにしましょう。app.html ファイルで、最後の例の material と category の div タグを lightning-badge コンポーネントに置き換えます。HTML は次のようになります。
<template> <template lwc:if={ready}> <div id="display"> <div>Name: {name}</div> <div>Description: {description}</div> <lightning-badge label={material}></lightning-badge> <lightning-badge label={category}></lightning-badge> <div>Price: {price}</div> <div><img src={pictureUrl} alt={name}/></div> </div> </template> <template lwc:else> <div id="waiting">Loading…</div> </template> </template>
ファイルを保存します。
Steel と Mountain という語がバッジとして表示されます。非常にシンプルです。
コンポーネントの構築構造
コンポーネントに必要なのは、同じ名前を持つフォルダーとファイルのみです。このフォルダーとファイルは名前と場所で自動的にリンクされます。
すべての Lightning Web コンポーネントには名前空間があり、フォルダー名とはハイフンで区切られます。たとえば、デフォルト名前空間 c 内にあるフォルダー名 app の Lightning Web コンポーネントのマークアップは <c-app>
です。
ただし、Salesforce Platform では、コンポーネントのフォルダー名やファイル名にハイフンの使用は許可されません。では、コンポーネント名が「mycomponent」のように複数の単語でできている場合はどうすればよいでしょうか? フォルダーとファイルに my-component という名前を付けることはできませんが、便利な解決策があります。
キャメルケースを使用してコンポーネント名を myComponent
にします。キャメルケースのコンポーネントフォルダー名をマークアップのケバブケース (ハイフンで結合された単語) に対応付けます。マークアップでフォルダー名 myComponent のコンポーネントを参照するには、<c-my-component>
を使用します。
たとえば、LWC サンプルリポジトリには、viewSource コンポーネントのファイルが含まれる viewSource フォルダーがあります。hello コンポーネントが HTML で viewSource コンポーネントを参照するときは、c-view-source
を使用します。
よろしいでしょうか。JavaScript を見てみましょう。
JavaScript の処理
ここで実際の処理が行われます。これまで見てきたように、JavaScript メソッドは、入力、データ、イベント、状態への変更などの処理を定義して、コンポーネントを動作させます。
Lightning Web コンポーネントの JavaScript ファイルには、少なくとも次のコードを含める必要があります。MyComponent
は、コンポーネントクラスに割り当てる名前になります。
import { LightningElement } from 'lwc'; export default class MyComponent extends LightningElement { }
export
ステートメントで、LightningElement
クラスを拡張するクラスを定義します。ベストプラクティスとして、クラスの名前は通常、JavaScript クラスのファイル名と同じにしますが、必須ではありません。
LWC モジュール
Lightning Web コンポーネントでは、モジュール (ECMAScript 6 で組み込みモジュールが導入されました) を使用して、コア機能をバンドルし、コンポーネントファイルの JavaScript がアクセスできるようにします。Lightning Web コンポーネントのコアモジュールは lwc
です。
モジュールを import
ステートメントで開始し、コンポーネントで使用するモジュールの機能を指定します。
import
ステートメントは、JavaScript が lwc
モジュールから LightningElement
機能を使用することを示しています。
// import module elements import { LightningElement} from 'lwc'; // declare class to expose the component export default class App extends LightningElement { ready = false; // use lifecycle hook connectedCallback() { setTimeout(() => { this.ready = true; }, 3000); } }
-
LightningElement
は、Lightning Web コンポーネントの基本クラスで、connectedCallback()
を使用できるようにします。
-
connectedCallback()
メソッドは、ライフサイクルフックの 1 つです。ライフサイクルフックについては、次のセクションで詳しく説明します。ここでは、ドキュメントオブジェクトモデル (DOM) にコンポーネントが挿入されるとメソッドがトリガーされるということを知っておいてください。この場合は、タイマーが開始されます。
ライフサイクルフック
Lightning Web コンポーネントでは、コンポーネントのライフサイクルで重要なイベントは発生したらコードを「フック」できるようにするメソッドが提供されています。こうしたイベントとして、コンポーネントに次の変化があった場合などが含まれます。
- 作成
- DOM に追加された
- ブラウザーで表示された
- エラーが発生した
- DOM から削除された
こうしたライフサイクルイベントにコールバックメソッドを使用して対応できます。たとえば、connectedCallback()
は、コンポーネントが DOM に挿入されると呼び出されます。disconnectedCallback()
は、コンポーネントが DOM から削除されると呼び出されます。
条件付き表示のテストに使用した JavaScript ファイルでは、connectedCallback()
を使用して、コンポーネントが DOM に挿入されたらコードが自動的に実行されるようにしました。コードは 3 秒待機してから、ready
を true
に設定します。
import { LightningElement } from 'lwc'; export default class App extends LightningElement { ready = false; connectedCallback() { setTimeout(() => { this.ready = true; }, 3000); } }
また、this
キーワードが使用されていたことに注目してください。JavaScript を記述したことがあればキーワードの使用に慣れているでしょう。this は、他の環境と同じに動作します。JavaScript のこの this
キーワードは、現在のコンテキストの最上位を示します。ここでは、コンテキストは this クラスです。connectedCallback()
メソッドは、最上位の ready 変数に値を割り当てます。これは、Lightning Web コンポーネントを使用して開発に JavaScript 機能を取り入れる方法のよい例です。this
に関する詳細情報へのリンクは、「リソース」セクションを参照してください。
デコレーター
デコレーターは、プロパティまたは関数の動作を変更するために JavaScript でよく使用されます。
デコレーターを使用するには、lwc
モジュールからインポートして、プロパティまたは関数の前に配置します。
import { LightningElement, api } from 'lwc'; export default class MyComponent extends LightningElement{ @api message; }
複数のデコレーターをインポートできますが、1 つのプロパティまたは関数に設定できるデコレーターは 1 つだけです。たとえば、プロパティに @api
デコレーターと @wire
デコレーターを設定することはできません。
Lightning Web コンポーネントデコレーターの例として、次のようなものがあります。
-
@api:: 項目を公開としてマークします。公開プロパティではコンポーネントの API を定義します。HTML マークアップでコンポーネントを使用する所有者コンポーネントは、コンポーネントの公開プロパティにアクセスできます。すべての公開プロパティはリアクティブです。つまり、フレームワークはプロパティの変更を監視します。プロパティの値が変更されると、フレームワークはそれに反応し、コンポーネントを再表示します。
-
@track: オブジェクトのプロパティまたは配列の要素の変更を監視するようにフレームワークに指示します。変更があると、フレームワークはコンポーネントを再表示します。すべての項目はリアクティブです。項目の値が変更され、その項目がテンプレートで使用されているか、テンプレートで使用されているプロパティの getter で使用されている場合、フレームワークはコンポーネントを再表示します。項目を
@track
でデコレートする必要はありません。@track
は、項目にオブジェクトまたは配列が含まれていて、フレームワークでオブジェクトのプロパティまたは配列の要素の変更を監視する場合にのみ使用します。プロパティ全体の値を変更する場合は、@track
を使用する必要はありません。
-
@wire:: Salesforce からデータを簡単に取得してバインドできるようにします。
@api
デコレーターを使用して、あるコンポーネント (bike) の値を別のコンポーネント (app) に表示する例を次に示します。ファイル構造は、次のとおりです。
app コンポーネントは、次の HTML を使用します。
<!-- app.html --> <template> <div> <c-bike bike={bike}></c-bike> </div> </template>
app コンポーネントは、次の JavaScript を使用します。
// app.js import { LightningElement } from 'lwc'; export default class App extends LightningElement { bike = { name: 'Electra X4', picture: 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg' }; }
bike コンポーネントは、次の HTML を使用します。
<!-- bike.html --> <template> <img src={bike.picture} alt="bike picture" /> <p>{bike.name}</p> </template>
bike コンポーネントは、次の JavaScript を使用します。
// bike.js import { LightningElement, api } from 'lwc'; export default class Bike extends LightningElement { @api bike; }
駆け足で進んでいますが、VS Code でコードを使用することができました。次の単元では、コードをリリースし、リリースコンポーネントが存在する環境について説明します。
リソース
- Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド): リアクティビティ
- Lightning Web Components Developer Guide (Lightning Web コンポーネント開発者ガイド): 参考文献 (HTML テンプレートディレクティブ、デコレーターなどを含む)
- MDN web docs:this