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 コードの共有