本記事の内容は旧 Lightning コンポーネント(現 Aura コンポーネント)に関するものであり、Lightning Web コンポーネントとは関係ありません。
記事内のLightning コンポーネントの記述は全て Aura コンポーネントの事だと思ってください。
ついでに、過去の記事についても書き直すつもりはないのでご了承ください(涙)
#Lightning コンポーネントバンドルの各ファイルについて
Lightning コンポーネントが出てきてからというもの、私自身結構な数のコンポーネントを作成してきましたが、同じ様に Lightning コンポーネントを開発する方によく聞かれるのが「それぞれのファイルに何を書いていいか分からない!」という悩みです。
そこで、(明確な答えがあるわけではないのですが)私なりの使い方を紹介してみようと思います。
Lightning コンポーネントの種類
まず、前提として Lightning コンポーネントは UI コンポーネント
と サービスコンポーネント
の 2 の種類に大別出来ちゃいます。
簡単にいうと UI があるかないかの違いです。
- UI コンポーネント
- UI と機能を提供するコンポーネント
- lightning:datatable や lightning:button など
- サービスコンポーネント
- UI を持たず機能のみを提供するコンポーネント
- 公式にこう呼ぶか分かりませんがドキュメントにたまに出てくるので覚えておいて損はありません
- lightning:navigation や force:recordData など
Lighting コンポーネントバンドルに含まれるファイル
一般的に Lightning コンポーネント
と呼ぶ時は、Lightning コンポーネントバンドル
のことを指しており、以下の通り複数のファイルのまとまりで構成されています。
厳密には他にもありますが、一般的な開発においてはこれだけ覚えておけば問題ありません。
- コンポーネント(~~~.cmp)
- コントローラ(~~~Controller.js)
- ヘルパー(~~~Helper.js)
- スタイル(~~~.css)
- レンダラ(~~~Renderer.js)
- デザイン(~~~.design)
- svg(~~~.svg)
それでは、それぞれのファイルについて詳しく見ていきましょう。
##コンポーネント(~~~.cmp)
コンポーネントは、Lighting コンポーネントバンドルを構成するファイルの中で唯一の必須ファイルです。
逆をいえば、コンポーネントだけで Lightning コンポーネントを成立させることが出来ます。
コンポーネントでは、Lightning コンポーネント内で利用するあらゆるリソースの宣言と定義をマークアップ形式で行います。
一見 HTML の様で UI を定義する物だと感じるかも知れませんが、そう思っていると混乱してしまうので気をつけましょう。コンポーネントは、Lightning コンポーネントの構成を定義する設定ファイルの様な物です。
ちなみに、ここでいうリソースとは以下を指します。(長くなるので詳しく解説はしません。ごめんなさい。)
- 外部ライブラリ
- コンポーネント属性
- コンポーネントメソッド
- イベント
- サービスコンポーネント
- UI
これらをコンポーネントのどこにどの順番で書くかは決められていませんが、私は下の様に書くようにしています。
##コントローラ(~~~Controller.js)
コントローラに記述するのは、イベントハンドラ関数です。
このファイルに記述した関数は全て、c(コントローラの値プロバイダー)に追加され、 コンポーネントから {!c.関数名} で呼び出せます。
コンポーネント上で発生したユーザインタラクションや、 Aura/Lightning のイベントを処理する関数を記述する事になるため、関数名としては処理の内容が分かる名前(submit/deleteRecord など)の他に、呼ばれるタイミング(onCancelClicked/onInitialized)とする事も多いです。
前述の通りコントローラの関数はイベントハンドラ関数であるという想定のため、コンポーネント以外からコントローラ関数が直接呼ばれる事はありません。
これにはもちろん他のコントローラ関数も含まれており、コントローラ関数をヘルパー関数的に使おうとするのも良くないです。
コントローラ関数は第 3 引数としてヘルパー関数オブジェクトへの参照を受け取るので、処理の分割やリファクタリングが必要な場合は、ヘルパー関数を呼びましょう。
コントローラ関数の第 2 引数にはイベントオブジェクトが渡されます。このオブジェクトは、 Locker サービスにより Proxy オブジェクト化されていますが、基本的には JS のイベントオブジェクトと同等のものとなっています。
覚えておくべき違いは、 event.getParams()
することでイベントパラメータオブジェクトを取得できるという言うことと、console.log(JSON.parse(JSON.stringify(event.getParams())));
とすれば中身を簡単に確認出来ると言うことくらいです。
##ヘルパー(~~~Helper.js)
ヘルパーの使い方は特に定められていませんが、js コードのリファクタリング目的で利用される事が多いです。
ヘルパーに記述した関数はヘルパーオブジェクトとしてコントローラやレンダラにまとめて渡されるので、冗長的なコードを書き出したり、ユーティリティ関数を記述したりします。
引数指定の決まりもありませんが、慣例的に第 1 引数にコンポーネントオブジェクト、第 2 引数にヘルパーオブジェクトを渡し、第 3 引数以降を自由に指定する事が多いようです。
ユーティリティ関数などは別の js ファイルに記述し、静的リソースにアップロードした上でコンポーネントから読み込むことも可能です。
こうする事で、複数コンポーネントのヘルパーに同じ関数を繰り返し記述せずに済むという利点がある一方、ライブラリの読み込みが完了していない(コンポーネントの初期化時などの)タイミングでは使えないので注意が必要です。
ヘルパー関数の記述で気をつける点は、実行タイミングによらず動作するように作る事です。
実行タイミングが明確に分かるコントローラ関数やレンダラ関数とは違い、いつ呼ばれるか分からないヘルパー関数はいずれのタイミングで呼ばれても動作する様に作られている必要があります。例えば、レンダリングの完了していない初期化時に DOM にアクセスしようとすればエラーになります。また、 jQuery などの外部ライブラリの読み込みが完了していないのにアクセスすれば当然エラーになります。この様に動作がタイミングに依存する記述は、コントローラやレンダラ側に記述した方がいい場合があります。
##スタイル(~~~.css)
コンポーネント固有のスタイルを記述します。
注意点としては、常に .THIS を記述しなければならない点です。しないとエラーになります。
Lightning コンポーネントでは、コンポーネントに記述した最上位タグに cコンポネント名
の形式で自動でクラスが割り当てられます。 一方スタイルシート側の .THIS は .cコンポネント名 に置き換えられるため、スタイルが提供される範囲がコンポーネント内に限られる仕組みなっています。
##レンダラ(~~~Renderer.js)
Lighting フレームワークにおけるレンダリングとは、コンポーネントファイルに記述したタグを読み込み、 HTML として吐き出す処理です。また、HTML の構成に関わる属性値が変更された際に、それを検知し HTML を再構築した上で吐き出す処理もあります。
レンダラでは、Lightning コンポーネントのレンダリングのタイミングで呼ばれる関数をオーバーライド出来ます。つまり構築された HTML を変更したり、HTML の描画が完了したタイミングを知る事が出来ます。オーバーライド出来る関数は以下の 4 つです。
- render(): 画面に描画される直前の DOM にアクセスできる
- rerender(): 再描画が完了した際に呼び出される。
- afterRender(): 初回描画の完了時に 1 回だけ呼び出される
- unrender(): コンポーネントが破棄された際に呼び出される。
中でもよく使うのは afterRender
で、初回描画の完了時に呼ばれます。 document.getElementById
など DOM に直接アクセスする場合はafterRender
の中、もしくはこの afterRender
から呼ばれるヘルパーで実行する様にしましょう。
レンダラ関数は、第 2 引数にヘルパーオブジェクトへの参照が渡されるため、コントローラ関数と同じようにヘルパー関数を呼び出す事が出来ます。しかし、コントローラ関数やヘルパー関数から直接呼び出す事は出来ません。
##デザイン(~~~.design)
コンポーネントのプロパティをで設定するため UI の構成を記述できます。
例えば、アプリケーションビルダーやコミュニティビルダーでコンポーネントを配置した際に表示される設定画面がこれにあたります。
その他にも、 LEX のユーティリティバーやフローに追加する際にも表示されます。
##svg(~~~.svg)
最後は svg です。
コンポーネントのアイコンを svg で指定できます。
App Exchange に公開する場合や、コンポーネントをブランディングする際に使うと格好いいのではないでしょうか。
最後に
個人的に溜め込んでいた情報を吐き出してみましたが、いかがでしたでしょうか。
Lightning コンポーネントの開発方法で迷っている方や、これから開発しようとしている方の少しでもお役に立てたら嬉しいです。
これらは、あくまで私が個人的に試行錯誤の結果たどり着いたルールですので、「こうした方がいいよ!」というご意見もお待ちしています!
Lightning コンポーネントは、まだまだ開発者も少なく、情報はもっと少ない現状ですが、一緒にがんばりましょう。