Skip to main content

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 に貼り付けていきます。

  1. VS Code のコマンドパレットの [SFDX: Create Project (SFDX: プロジェクトを作成)] を選択してプロジェクトを作成します。標準テンプレートを受け入れ、bikeCard というプロジェクト名を付けます。
  2. force-app/main/default で、lwc フォルダーを右クリックし、[SFDX: Create Lightning Web Component (SFDX: Lightning Web コンポーネントの作成)] を選択します。
  3. 新しいコンポーネントの名前に app と入力します。
  4. Enter キーを押し、もう一度 Enter キーを押してデフォルトの force-app/main/default/lwc を受け入れます。
  5. 次のコードを 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 クラス内の同じ名前の項目にバインドされます。
  6. 次のコードを 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';
    }
  7. ファイルを保存します。

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

  1. 次のコードを 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>
  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>
  <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>

ファイルを保存します。

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

コンポーネントの構築構造

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

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

すべての 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 秒待機してから、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;
}

駆け足で進んでいますが、VS Code でコードを使用することができました。次の単元では、コードをリリースし、リリースコンポーネントが存在する環境について説明します。

リソース

Salesforce ヘルプで Trailhead のフィードバックを共有してください。

Trailhead についての感想をお聞かせください。[Salesforce ヘルプ] サイトから新しいフィードバックフォームにいつでもアクセスできるようになりました。

詳細はこちら フィードバックの共有に進む