JavaScript の移行
学習の目的
この単元を完了すると、次のことができるようになります。
- Aura コンポーネントから Lightning Web コンポーネントへ JavaScript を移行する。
- Aura コンポーネントと Lightning Web コンポーネント間でコードを共有する。
JavaScript モジュールの使用
JavaScript は Lightning Web コンポーネントの鼓動する心臓です。JavaScript がなければ、コンポーネントは大部分が生気のない HTML の塊になります。前の単元では、Lightning Web コンポーネントの JavaScript ファイルを少しだけ見て、Aura コンポーネントの属性が JavaScript プロパティにどのようにマッピングされるのか確認しました。次は、JavaScript ファイルを詳しく見ていきます。
Aura コンポーネントのクライアント側コントローラー、ヘルパー、レンダラーの個別ファイルの JavaScript コードを、Lightning Web コンポーネントの 1 つの JavaScript ファイルに移行します。
Aura コンポーネントのクライアント側コントローラーは、名前―値ペアのマッピングを含むオブジェクトリテラル表記法の JavaScript オブジェクトです。言葉数が多いですね。PropertyPaginatorController.js ファイルの例を見てみましょう。
({ previousPage : function(component) { var pageChangeEvent = component.getEvent("pagePrevious"); pageChangeEvent.fire(); }, nextPage : function(component) { var pageChangeEvent = component.getEvent("pageNext"); pageChangeEvent.fire(); } })
Aura コンポーネントの JavaScript ファイルの形式は、JavaScript クラスやモジュールなどの機能の ES6 標準が確立される数年前に設計されました。
Lightning Web コンポーネントの JavaScript ファイルは ES6 モジュールなので、Aura コンポーネントで使用される専有形式ではなく、標準の JavaScript を使用しています。あなたが記述する JavaScript は、その他の最新の JavaScript フレームワーク向けに記述される JavaScript によく似ています。
以下は、paginator Lightning Web コンポーネントの JavaScript です。
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; previousHandler() { this.dispatchEvent(new CustomEvent('previous')); } nextHandler() { this.dispatchEvent(new CustomEvent('next')); } get currentPageNumber() { return this.totalItemCount === 0 ? 0 : this.pageNumber; } get isFirstPage() { return this.pageNumber === 1; } get isLastPage() { return this.pageNumber >= this.totalPages; } get totalPages() { return Math.ceil(this.totalItemCount / this.pageSize); } }
コードを 1 行ずつ見ていくことはしません。主に重要なのは、Lightning Web コンポーネントでは標準の JavaScript モジュールが使用されるということです。それは良いことです。
Aura コンポーネントと Lightning Web コンポーネント間でのコードの共有
Lightning Web コンポーネントと Aura コンポーネントの間で JavaScript コードを共有するには、コードを ES6 モジュールに配置します。どちらのプログラミングモデルでも共有されたコードにアクセスできます。Lightning Web コンポーネントにすべてのコードを移行しない場合でも、Aura コンポーネントの ES6 モジュールで記述する新しい機能にアクセスできます。
utils.js ES6 モジュールの例を見てみましょう。
/* utils.js */ /** * Returns whether provided value is a function * @param {*} value - the value to be checked * @return {boolean} true if the value is a function, false otherwise */ export function isFunction(value) { return typeof value === 'function'; }
utils モジュールは、指定したパラメーターが関数かどうかを返す isFunction() 関数をエクスポートします。
以下は、utils モジュールを使用する c-libcaller Lightning Web コンポーネントです。
/* libcaller.js */ import { LightningElement } from 'lwc'; // import the library import { isFunction } from 'c/utils'; export default class LibCaller extends LightningElement { result; checkType() { // Call the imported library function this.result = isFunction( function() { console.log('I am a function'); } ); } }
c-libcaller コンポーネントは utils モジュールをインポートし、モジュールによってエクスポートされた isFunction 関数をコールします。isFunction に渡される引数は関数なので、result
は true に設定されます。
次は、同じく utils モジュールを使用する libcallerAura.cmp ファイルを見てみましょう。
<aura:component> <aura:handler name="init" value="{!this}" action="{!c.doInit}"/> <p>Aura component calling the utils lib</p> <!-- add the lib component --> <c:utils aura:id="utils" /> </aura:component>
libcallerAura Aura コンポーネントには c:utils ES6 モジュールへの参照が含まれています。JavaScript コードでモジュールの参照を取得できるように aura:id を追加しました。
以下は、libcallerAuraController.js ファイルです。
({ doInit: function(cmp) { // Call the lib here var libCmp = cmp.find('utils'); var result = libCmp.isFunction( function() { console.log(" I am a function"); } ); console.log("Is it a function?: " + result); } })
コンポーネントのコントローラーは cmp.find('utils') を使用して、マークアップの aura:id に一致させ、モジュールの参照を取得します。utils ES6 モジュールは isFunction() をエクスポートします。これは Aura コンポーネントをコールします。isFunction() に渡される引数は関数なので、result
は true に設定されます。
サードパーティ JavaScript ライブラリの使用
Aura コンポーネントまたは Lightning Web コンポーネントでサードパーティ JavaScript ライブラリを使用するには、ライブラリを静的リソースとしてアップロードする必要があります。静的リソースを操作する構文は、2 つのプログラミングモデルで異なります。
Aura コンポーネントでは、マークアップで <ltng:require> タグを使用して静的リソースを読み込みます。
<ltng:require scripts="{!$Resource.resourceName}" afterScriptsLoaded="{!c.afterScriptsLoaded}" />
resourceName が静的リソースの名前です。スクリプトが読み込まれると、クライアント側コントローラーの afterScriptsLoaded アクションがコールされ、コンポーネントが表示されます。
Lightning Web コンポーネントでは、JavaScript で静的リソースをインポートします。
import resourceName from '@salesforce/resourceUrl/resourceName';
その後、loadScript と loadStyle を使用してサードパーティライブラリを読み込みます。
インポートされたライブラリの使用についての詳細は、『Lightning Web コンポーネント開発者ガイド』の「サードパーティ JavaScript ライブラリの使用」を参照してください。
コンポーネントの動的な作成
Aura コンポーネントでは、$A.createComponent() を使用して JavaScript でコンポーネントを動的に作成できます。Lightning Web コンポーネントには、コンポーネントの動的な作成に相当するものはありません。
このアーキテクチャに関する決定は意図的なものです。Lightning Web コンポーネントでこのパターンを再現しない主な理由は、Aura コンポーネントでは、このパターンがバグの多い複雑なコードにつながったからです。
改善策として、Lightning Web コンポーネントでは、コンポーネントに複数の HTML テンプレートを作成します。コンポーネントの render() メソッドで、コンポーネントのニーズに基づいてテンプレートを切り替えることができます。このパターンは、他の JavaScript フレームワークで使用されたルート分割により似ています。
リファクタリングの機会
JavaScript コードを移行するとき、それは 1 行ごとの変換ではありません。これはコンポーネントの設計を見直す良い機会です。
新しいプログラミングモデルへの移行は、同じ目的地につながる新しい道を進むようなものです。途中の景色や音 (そして記述するコード) が違います。
コンポーネントの移行は、Aura コンポーネントではおそらく使用していない JavaScript モジュールなどの新しい ES6 機能を使用する良い機会でもあります。
これらの新機能の概要は、「JavaScript の最新機能」 Trailhead モジュールを参照してください。
リソース
- Lightning Aura コンポーネント開発者ガイド: JavaScript の使用
- Lightning Web コンポーネント開発者ガイド: LWC と Aura 間での JavaScript コードの共有