Skip to main content

Lightning Web コンポーネントの作成

学習の目的

この単元を完了すると、次のことができるようになります。

  • 各コンポーネントファイルの内容を説明する。
  • Lightning Web コンポーネントの JavaScript メソッドを作成する。
  • コンポーネント JavaScript でライフサイクルフックを使用する。

さらに実践してみよう

Salesforce の特定のオブジェクトとは関係なく、データ表示要素を作成するとします。ぴったりの例が、ebikes サンプルリポジトリにある productCard component です。そのカードコンポーネントを調べ、独自のバージョンをゼロから作成して、どうすればそれが本格的な Lightning Web コンポーネントに進化するのかを確認しましょう。コンポーネントの各部を構築し、他のサンプルを見て回ることで、すぐに基本を習得できます。

コンポーネントに必要なのは、同じ名前を持つフォルダーとファイルのみです。このフォルダーとファイルは名前と場所で自動的にリンクされます。

フォルダー内のコンポーネントファイル

すべての 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 を使用します。

HTML ファイルの中身

Lightning Web コンポーネントの HTML ファイルのすべてに、template タグが含まれます。template タグには、コンポーネントの構造を定義する HTML が含まれます。ebikes リポジトリにある productCard コンポーネントの簡易バージョンの HTML を見てみましょう

以下の例を LWC.studio に貼り付けていきます。

  1. LWC.studio に移動します。
  2. まだログインしていない場合は、GitHub アカウントを使用してログインして、[新規] をクリックします。
  3. 次のコードを 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}/></div>
        </div>
    </template>
    中括弧 {} で囲まれた識別子は、対応する JavaScript クラス内の同じ名前の項目にバインドされます。
  4. 次のコードを 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';
    }
  5. ファイルを保存します。

ピカピカの自転車が表示されます。

では、実例を使って試してみましょう。たとえば、データを表示するのに、読み込みに少し時間がかかることがわかっているとします。何かあったのかとユーザーを心配させたくありません。テンプレート内で if:false および if:true 条件付きディレクティブを使用して、どの視覚要素が表示されているかを判別できます。

  1. 次のコードを app.html に貼り付けます。"display" div タグ内のコンテンツは、HTML ファイルの ready の値が true になるまで表示されません。
    <template>
        <div id="waiting" if:false={ready}>Loading…</div>
        <div id="display" if:true={ready}>
            <div>Name: {name}</div>
            <div>Description: {description}</div>
            <div>Category: {category}</div>
            <div>Material: {material}</div>
            <div>Price: {price}</div>
            <div><img src={pictureUrl}/></div>
        </div>
    </template>
  2. 次のコードを 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);
       }
    }
  3. ファイルを保存します。

基本 Lightning Web コンポーネント

すべてのコンポーネントをゼロから作成したくはないでしょう。そこで、基本 Lightning Web コンポーネントを使用することを検討します。当然、データ型、表示コントローラー、ナビゲーション項目など、多くのコンポーネントがあります。そのすべては、「Component Reference (コンポーネントリファレンス)」にリストされています。

自転車の詳細が目立つようにしましょう。app.html ファイルで、最後の例の material と category の div タグを lightning-badge コンポーネントに置き換えます。HTML は次のようになります。

<template>
    <div id="waiting" if:false={ready}>Loading…</div>
    <div id="display" if:true={ready}>
        <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}/></div>
    </div>
</template>

ファイルを保存します。

SteelMountain という語がバッジとして表示されます。非常にシンプルです。

Lightning バッジを使用

よろしいでしょうか。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 秒待機してから、readytrue に設定します。

import { LightningElement } from 'lwc';
export default class App extends LightningElement {
    ready = false;
    connectedCallback() {
        setTimeout(() => {
            this.ready = true;
        }, 3000);
    }
}
メモ

この例を VS Code などのエディターで使用すると、setTimeout() 関数に「Restricted async operation.... (制限された非同期操作....)」という Lint 警告表示されることがあります。この警告は、誤用されることが多い非同期操作を使用していることを示していて、イベントを待つのではなく時間に基づいて動作を遅延します。その場合、setTimeout() は任意の遅延時間を示すのに適しており、警告が表示されても問題なく使用できます。

また、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 マークアップでコンポーネントを使用する所有者コンポーネントは、コンポーネントの公開プロパティにアクセスできます。すべての公開プロパティはリアクティブです。つまり、フレームワークはプロパティの変更を監視します。プロパティの値が変更されると、フレームワークはそれに反応し、コンポーネントを再表示します。
    ヒント

    項目とプロパティはほぼ同義の用語です。コンポーネントの作成者は JavaScript クラスで項目を宣言します。クラスのインスタンスはプロパティを持ちます。コンポーネントのコンシューマーにとって、項目はプロパティです。Lightning Web コンポーネントでは、コンポーネントの作成者が @api でデコレートした項目のみが、オブジェクトプロパティとしてコンシューマーに公開されます。

  • @track: オブジェクトのプロパティまたは配列の要素の変更を監視するようにフレームワークに指示します。変更があると、フレームワークはコンポーネントを再表示します。すべての項目はリアクティブです。項目の値が変更され、その項目がテンプレートで使用されているか、テンプレートで使用されているプロパティの getter で使用されている場合、フレームワークはコンポーネントを再表示します。項目を @track でデコレートする必要はありません。@track: は、項目にオブジェクトまたは配列が含まれていて、フレームワークでオブジェクトのプロパティまたは配列の要素の変更を監視する場合にのみ使用します。プロパティ全体の値を変更する場合は、@track を使用する必要はありません。
    メモ

    Spring '20 より前は、項目 (非公開プロパティともいう) をリアクティブとしてマークするために @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;
}

駆け足で進んでいますが、いくつか試すことができました。次の単元では、一歩下がって、コンポーネントが存在する環境について説明します。

リソース

無料で学習を続けましょう!
続けるにはアカウントにサインアップしてください。
サインアップすると次のような機能が利用できるようになります。
  • 各自のキャリア目標に合わせてパーソナライズされたおすすめが表示される
  • ハンズオン Challenge やテストでスキルを練習できる
  • 進捗状況を追跡して上司と共有できる
  • メンターやキャリアチャンスと繋がることができる